Compare commits

...

70 Commits

Author SHA1 Message Date
113a8294ad Documented changes and 0.3.2 release timestamp 2007-02-10 14:38:54 +00:00
86ac7a9754 Made number transition and activated development documentation 2007-02-10 14:24:30 +00:00
537a8ee1d7 Updated cdrskin tarball generator 2007-02-10 12:31:08 +00:00
d95f777bd8 Created 0.3.2 tag 2007-02-09 23:33:14 +00:00
e8d210e15f Small corrections in documentation 2007-02-09 16:14:47 +00:00
6df2745652 Added special thanks towards Andy Polyakov 2007-02-09 16:01:45 +00:00
09b5bd2a1f Silenced compiler warning 2007-02-08 22:53:22 +00:00
67ce096aeb Mentioned DVD-R 2007-02-08 21:29:33 +00:00
cad7531058 New option --prodvd_cli_compatible 2007-02-08 21:09:10 +00:00
8dccb584b4 Finally made tests with DVD-R. They burn indeed like DVD-RW. 2007-02-08 14:10:05 +00:00
50eba7ee31 Updated documentation aspects 2007-02-07 17:49:52 +00:00
494693cc63 Made use of burn_write_opts_auto_write_type() 2007-02-07 16:37:25 +00:00
05623cffc4 New API function burn_write_opts_auto_write_type() 2007-02-07 16:30:42 +00:00
fed2af8c69 Next cdrskin-0.3.1 cycle 2007-02-06 21:22:41 +00:00
78f1cf835d Described DVD-R[W] DAO mode 2007-02-06 19:21:20 +00:00
d2283a5b4e Clarified CD and DVD peculiarities 2007-02-06 19:19:54 +00:00
8dd8ee4b9c Enabled fast blank for DVD-R[W] 2007-02-06 18:57:38 +00:00
6dfbbdf57f tao_to_sao_tsize= for DVD-R[W] DAO 2007-02-06 17:45:17 +00:00
d57166f64b Beautification of debugging messages 2007-02-06 17:08:15 +00:00
2799fe1b44 Implemented DVD-R[W] DAO as BURN_WRITE_SAO 2007-02-06 13:06:39 +00:00
330e0e2d5f Preparations for DVD-R[W] DAO 2007-02-05 13:28:57 +00:00
135d9d5016 New in API : struct burn_multi_caps and burn_disc_get_multi_caps() 2007-02-04 07:30:14 +00:00
db9f4a1d04 Mentioned DVD-RW multi-session 2007-02-03 18:46:42 +00:00
6b8ab52854 Improved classification and TOC of finalized DVD-R[W] media 2007-02-02 17:32:09 +00:00
4e93de2cd2 Make mmc_read_multi_session_c1 use TOC if available 2007-02-02 15:11:35 +00:00
a769f8aa87 Updated about DVD-R[W] blanking, multi-session info and TOC 2007-02-02 13:39:30 +00:00
e0a38be97b Some sed expressions for beautification 2007-02-02 13:37:34 +00:00
100de7b160 Mentioned DVD-RW multi-session in overview of features 2007-02-01 20:14:01 +00:00
9f7e5dd6dd Mentioned DVD-RW multi-session in overview of features 2007-02-01 20:06:03 +00:00
a9ac7ae480 Prepared next cdrskin-0.3.1 cycle 2007-02-01 19:53:07 +00:00
2e75680ed7 Prepared next cdrskin-0.3.1 cycle 2007-02-01 19:45:47 +00:00
c02dbe4eca Allowed blanking of DVD-RW which offer no Incremental Streaming 2007-02-01 19:15:06 +00:00
f3a08f6812 Reacted on justified compiler warning about unitialized sessions variable 2007-02-01 16:33:27 +00:00
e876f90e6c Obtain TOC from non-CD via 52h READ TRACK INFORMATION 2007-02-01 16:15:09 +00:00
dde52c1971 Provisorily obtain multi-session -C parameters (violates MMC specs but works) 2007-01-31 17:34:49 +00:00
f194aa8d5d Blank sequential DVD-RW, deformat overwriteable DVD-RW 2007-01-31 12:59:51 +00:00
b18b889750 Enabled Burnfree buffer underrun protection by default 2007-01-30 22:01:10 +00:00
0aafc18ac7 Added snapshot of emerging sequential DVD-R[W] cookbook 2007-01-30 20:16:55 +00:00
fa792f6a67 First successful multi-session write to a sequential DVD-RW 2007-01-30 19:16:35 +00:00
53a1e99675 Preparations for DVD-R[W] Sequential Recording 2007-01-30 17:54:39 +00:00
bda139f390 Experiments about list of features and profiles 2007-01-29 17:57:31 +00:00
ff7028d1fc Added a statement about blanking of DVD-RW 2007-01-29 17:52:36 +00:00
fa350edaae Initialized member set_size of burn_source within burn_null_source_new() 2007-01-26 17:33:29 +00:00
55e6c0ba82 Unified burn_file_source and burn_fd_source 2007-01-26 17:32:31 +00:00
f5a350f2cc Now offering cdrskin-0.3.0.pl01 for download 2007-01-26 11:09:07 +00:00
c079e09860 Enforce minimum track length with SAO 2007-01-25 18:52:50 +00:00
99f8e0eec5 Bug fix: DVD tracks of defined size >=2GB suffered 32-bit integer wraparound 2007-01-25 15:00:37 +00:00
3aec7fdeda Restored FreeBSD backend. 2007-01-24 12:44:22 +00:00
814d8cc83d Removed libisofs specific bits. 2007-01-24 12:41:25 +00:00
bc694d7457 Corrections of typos and text debris 2007-01-23 21:34:13 +00:00
66d70075ec Added SAO CD Cookbook 2007-01-23 10:35:51 +00:00
8f4dd8580c Banned mixed mode SAO (because broken in libburn and unclear in MMC) 2007-01-22 11:42:17 +00:00
7dd845a83b Clarification about TAO and mode page 05h per track 2007-01-21 19:13:27 +00:00
7b024f4a72 Comments learned from studying MMC-3 and MMC-5 for SAO CD cookbook 2007-01-21 19:10:37 +00:00
f1215f3295 Removed unnecessary after-grab loops 2007-01-21 19:09:07 +00:00
8e17806405 Changes with CD part. Especially explanation of TOC. 2007-01-20 14:26:32 +00:00
fb98c0390e Began to describe TAO multi-session CD writing 2007-01-19 20:54:11 +00:00
f418c49e63 Removed forgotten debug message printed to stderr 2007-01-19 11:05:18 +00:00
a34e872511 Kept DVD+RW from stopping BG formatting if it was not started at all 2007-01-18 21:18:03 +00:00
69a07aeec6 Made clarification about formatting state recognition 2007-01-18 21:16:13 +00:00
7addf0d5b5 More info about Current/Maximum Capacity Descriptor 2007-01-18 14:33:53 +00:00
a001f96b21 Wrote down what i learned from implementing support for overwriteable DVD 2007-01-18 13:55:28 +00:00
4a26017f2a Removed paragraph about obsoleted tao_to_sao_tsize= 2007-01-17 13:00:05 +00:00
0f48910aff Next cdrskin-0.3.1 cycle 2007-01-16 15:44:39 +00:00
c68efb346c Corrected typo 2007-01-16 15:18:34 +00:00
36f287d569 Corrected old libburn.pykix.org URL 2007-01-16 15:15:08 +00:00
4d7e28c09f Made version number transition to 0.3.1 2007-01-16 15:11:41 +00:00
c1342195f6 Updated cdrskin tarball generator 2007-01-16 15:07:09 +00:00
1fd003c1ec Next cdrskin-0.2.7 cycle 2007-01-15 15:30:41 +00:00
36d475eaf9 Updated about overwriteable DVD and pointer to dvd+rw-tools 2007-01-15 12:58:49 +00:00
34 changed files with 4185 additions and 1066 deletions

View File

@ -101,9 +101,9 @@ test_structest_CPPFLAGS = -Ilibburn
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_structest_SOURCES = test/structest.c
## cdrskin construction site - ts A60816
## cdrskin construction site - ts A60816 - A70210
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_2_7
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_3_2
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
##

34
README
View File

@ -54,7 +54,8 @@ See README file there.
Overview of libburnia.pykix.org
libburnia.pykix.org is an open-source software project for reading, mastering
and writing optical discs. For now this means only CD-R and CD-RW.
and writing optical discs.
For now this means only CD media and all single layer DVD media except DVD+R.
The project comprises of several more or less interdependent parts which
together strive to be a usable foundation for application development.
@ -66,10 +67,10 @@ we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
We do have a workable code base for burning data CDs, though. The burn API is
quite comprehensively documented and can be used to build a presentable
application.
We do have a functional binary which emulates parts of cdrecord in order to
We have a workable code base for burning CD and most single layer DVD.
The burn API is quite comprehensively documented and can be used to build a
presentable application.
We have a functional binary which emulates parts of cdrecord in order to
prove that usability, and in order to allow you to explore libburnia's scope
by help of existing cdrecord frontends.
@ -78,20 +79,25 @@ The project components (list subject to growth, hopefully):
- libburn is the library by which preformatted data get onto optical media.
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
/dev/hdX (e.g. on kernel 2.6).
libburn is the foundation of our cdrecord emulation.
libburn is the foundation of our cdrecord emulation. Its code is
independent of cdrecord. Its DVD capabilities are learned from
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
the pure SCSI knowledge has been taken from dvd+rw-tools, though.
- libisofs is the library to pack up hard disk files and directories into a
ISO 9660 disk image. This may then be brought to CD via libburn.
ISO 9660 disk image. This may then be brought to media via libburn.
libisofs is to be the foundation of our upcoming mkisofs emulation.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
Cdrecord is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for
the services traditionally provided by cdrecord.
the services traditionally provided by cdrecord. Additionally it
provides libburn's DVD capabilities, where only -sao is compatible
with cdrecord.
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord
runs, though.
See cdrskin/README for more.
See cdrskin/README and man cdrskin/cdrskin.1 for more.
- test is a collection of application gestures and examples given by the
authors of the library features. The main API example for libburn
@ -178,6 +184,16 @@ Project history as far as known to me:
libburn, is now called libburnia. For the origin of this name, see
http://en.wikipedia.org/wiki/Liburnians .
- 16th January 2007 release of libburn-0.3.0 and cdrskin-0.3.0 . Now the scope
is widened to a first class of DVD media: overwriteable single layer types
DVD-RAM, DVD+RW, DVD-RW. This is not a cdrecord emulation but rather inspired
by dvd+rw-tools' "poor man" writing facility for this class of media.
Taking a bow towards Andy Polyakov.
- 11th February 2007 version 0.3.2 covers sequential DVD-RW and DVD-R with
multi-session and with DAO.
This means all single layer DVD media except DVD+R are supported now.
------------------------------------------------------------------------------

View File

@ -26,12 +26,12 @@ following possible.
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburnia.pykix.org but also published via:
http://scdbackup.sourceforge.net/cdrskin_eng.html
http://scdbackup.sourceforge.net/cdrskin-0.2.7.tar.gz
http://scdbackup.sourceforge.net/cdrskin-0.3.2.pl00.tar.gz
Copyright (C) 2006-2007 Thomas Schmitt
------------------------------------------------------------------------------
On top of libburn there is implemented cdrskin 0.2.7, a limited cdrecord
On top of libburn there is implemented cdrskin 0.3.2, a limited cdrecord
compatibility wrapper which allows to use some libburn features from
the command line.
Interested users of cdrecord are invited to participate in the development
@ -59,16 +59,16 @@ systems, including 64 bit systems. (Further reports are welcome.)
Compilation, First Glimpse, Installation
Obtain cdrskin-0.2.7.tar.gz, take it to a directory of your choice and do:
Obtain cdrskin-0.3.2.pl00.tar.gz, take it to a directory of your choice and do:
tar xzf cdrskin-0.2.7.tar.gz
cd cdrskin-0.2.7
tar xzf cdrskin-0.3.2.pl00.tar.gz
cd cdrskin-0.3.2
Or obtain a libburnia.pykix.org SVN snapshot,
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
Within that toplevel directory of either cdrskin-0.2.7 or libburn then execute:
Within that toplevel directory of either cdrskin-0.3.2 or libburn then execute:
./configure
make
@ -143,6 +143,9 @@ It is not checked for the necessary degree of hacker safety.
Usage examples
For options and recordable media classes see
man 1 cdrskin
Get an overview of cdrecord style addresses of available devices
cdrskin -scanbus
cdrskin dev=ATA -scanbus
@ -158,21 +161,34 @@ Obtain some info about the drive
Obtain some info about the drive and the inserted media
cdrskin dev=0,1,0 -atip -v
Thoroughly blank a CD-RW
cdrskin -v dev=0,1,0 blank=all -eject
Blank CD-RW sufficiently for making it ready for overwrite
Make used CD-RW or used unformatted DVD-RW writeable again
cdrskin -v dev=0,1,0 blank=fast -eject
Burn image file my_image.iso to CD or DVD+-RW
Format DVD-RW to avoid need for blanking before re-use
cdrskin -v dev=0,1,0 blank=format_overwrite
De-format DVD-RW to make it capable of multi-session again
cdrskin -v dev=/dev/sr0 blank=deformat_sequential
Burn image file my_image.iso to media
cdrskin -v dev=0,1,0 speed=12 fs=8m driveropts=burnfree padsize=300k \
-eject my_image.iso
Burn a compressed afio archive to CD or DVD+-RW on-the-fly
Write several sessions to the same CD or DVD-R[W]
cdrskin dev=/dev/hdc padsize=300k -multi 1.iso
cdrskin dev=/dev/hdc padsize=300k -multi -tao 2.iso
cdrskin dev=/dev/hdc padsize=300k -multi -tao 3.iso
cdrskin dev=/dev/hdc padsize=300k -tao 4.iso
Get CD or DVD-R[W] multi-session info for option -C of program mkisofs:
c_values=$(cdrskin dev=/dev/hdc -msinfo 2>/dev/null)
mkisofs ... -C "$c_values" ...
Burn a compressed afio archive to media on-the-fly
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 -tao \
driveropts=burnfree padsize=300k -
Burn 6 audio tracks from files with different formats to CD.
Burn 6 audio tracks from files with different formats to CD (not to any DVD).
Anything except .wav or .au files has to be converted into raw format first.
See below "Audio CD" for specifications.
ogg123 -d raw -f track01.cd /path/to/track1.ogg
@ -208,11 +224,12 @@ Run a backup :
Restrictions
The major restrictions are lifted now: audio, TAO, multi-session do work.
Many cdrecord options are still unsupported, though.
Many cdrecord options are still unsupported, though.
If you have use cases for them, please report your wishes and expectations.
DVD support is still immature and restricted to DVD+-RW for now.
DVD support is restricted to single layer overwriteable DVD (-RAM, +RW, -RW)
for now.
@ -232,6 +249,10 @@ Actually i, Thomas Schmitt, am a devoted user of cdrecord via my project
scdbackup which still runs a bit better with cdrecord than with cdrskin. TAO.
I have the hope that Joerg feels more flattered than annoyed by cdrskin.
Many thanks to Andy Polyakov for his dvd+rw-tools
http://fy.chalmers.se/~appro/linux/DVD+RW/tools
which provide me with examples and pointers into MMC specs for DVD writing.
Drive Addressing
@ -399,22 +420,36 @@ into the format of the burned data. Be advised to use growisofs for the
task of maintaining extendable ISO-Filesystems on DVD+RW.
DVD-RW
DVD-RW and DVD-R
DVD-RW are usable if formatted to state "Restricted Overwrite" or if in state
"Sequential Recording". DVD-R are always in sequential state.
DVD-RW are usable if formatted to state "Restricted Overwrite". They then
behave much like DVD+RW. See above.
DVD-RW in state "Sequential" have first to be formatted by
cdrskin dev=... -v blank=format_overwrite
"Sequential" is the state of unused media and of media previously blanked
or written by cdrecord. dvd+rw-format -blank can also achieve this state.
(Command dvd+rw-format -force can achieve "Restricted Overwrite".)
The according cdrskin option is blank=deformat_sequential .
If "Incremental Streaming" is available, then sequential media are capable
of multi-session like CD-R[W]. (But not capable of -audio recording.)
This means they need option -multi to stay appendable, need to be blanked
to be writeable from start, return useable info with -toc and -msinfo,
eventually perform appending automatically.
Without "Incremental Streaming" offered by the drive, only write mode DAO is
available with sequential DVD-R[W]. It only works with blank media, allows only
one single track, no -multi, and demands a fixely predicted track size.
(growisofs uses it with DVD-R[W] if option -dvd-compat is given.)
Overwriteable DVD-RW behave much like DVD+RW. "Restricted" refers only to the
granularity of random access and block size which have always to be aligned to
full 32 kB. Sequential DVD-RW are converted into overwriteable DVD-RW by
cdrskin dev=... -v blank=format_overwrite
(Command dvd+rw-format -force can achieve "Restricted Overwrite", too.)
Formatting or first use of freshly formatted DVD-RW can produce unusual noises
from the drive and last several minutes. Depending on mutual compatibility of
drive and media, formatting can yield unusable media. It seems that those die
too on blanking by cdrecord or dvd+rw-format. Perils of DVD-RW, i fear.
too on blanking by cdrecord, dvd+rw-format or cdrskin. Perils of DVD-RW.
There are three formatting variants with cdrskin currently:
There are three DVD-RW formatting variants with cdrskin currently:
blank=format_overwrite uses "DVD-RW Quick" formatting (MMC-type 15h)
and writes a first session of 128 MB. This leads to media which are expandable
@ -423,12 +458,22 @@ and random addressable by cdrskin.
blank=format_overwrite_quickest uses "DVD-RW Quick" formatting (type 15h) too,
but leaves the media in "intermediate" state. In the first session of writing
one may only write sequentially to such a DVD. After that, it gets random
addressable by cdrskin.
addressable by cdrskin. DVD-ROM drives might show ill behavior with them.
blank=format_overwrite_full uses preferrably "Full Format" (type 00h).
This formatting lasts as long as writing a full DVD. It includes writing of
lead-out which is said to be good for DVD ROM compatibility.
De-formatting options are available to make overwriteable DVD-RW sequential:
blank=deformat_sequential performs thorough blanking of all states of DVD-RW.
blank=all and blank=fast perform the same thorough blanking, but refuse to do
this with overwriteable DVD-RW, thus preserving their formatting. The specs
allow minimal blanking but the resulting media on my drives offer no
Incremental Streaming afterwards. So blank=fast will do full blanking.
blank=deformat_sequential_quickest is faster but might yield DAO-only media.
Special compilation variations

View File

@ -20,27 +20,28 @@ set -x
# The script is to be run in the directory above the toplevel
# directory of libburn resp. cdrskin development.
#
# libburn version used: http://libburn.pykix.org
# The top level directory in the SVN snapshot is named
intermediate="./libburn_pykix"
# libburn source used: http://libburnia.pykix.org
# Downloaded by:
# $ svn co http://libburn-svn.pykix.org/trunk libburn_pykix
# $ svn co http://libburnia-svn.pykix.org/libburn/tags/... $intermediate
# packed up in a tarball just to save it from inadverted changes by
# $ tar czf libburn_svn.tgz libburn_pykix
original="./libburn_svn.tgz"
# $ tar czf libburn_svn.tgz $intermediate
original="./libburn_svn_release.tgz"
# Historic moments:
# original="./libburn_svn_A60815.tgz"
# original="./libburn_cdrskin_A60819.tgz"
# The top level directory in that snapshot is named
intermediate="./libburn_pykix"
# My changes are in libburn-0.2.3.ts.develop , mainly in ./cdrskin
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-release"
changes="./libburn-0.2.3.ts.develop"
skin_release="0.2.6"
patch_level=".pl01"
skin_release="0.3.2"
patch_level=".pl00"
skin_rev="$skin_release""$patch_level"
# The result directory and the name of the result tarballs
target="./cdrskin-${skin_release}"
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
@ -54,6 +55,9 @@ compile_cmd="./cdrskin/compile_cdrskin.sh"
compile_static_opts="-static"
compile_result="cdrskin/cdrskin"
man_to_html_cmd="./cdrskin/convert_man_to_html.sh"
man_page_html="cdrskin/man_1_cdrskin.html"
bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
bintarget_static="$bintarget_dynamic"-static
@ -122,6 +126,8 @@ do
rm "$cdrskin_target"/cdrskin_"$i"
fi
done
# Remove eventual SVN stuff from cdrskin directory
for i in .deps .dirstamp .libs
do
if test -e "$cdrskin_target"/"$i"
@ -130,6 +136,23 @@ do
fi
done
# Remove GIFs of cdrskin_eng.html
rm "$cdrskin_target"/doener_*.gif
# Remove automatically generated HTML man page
rm "$cdrskin_target"/man_1_cdrskin.html
# Remove all add_ts_changes_to_libburn besides this one
for i in "$cdrskin_target"/add_ts_changes_to_libburn*
do
if test $(basename "$0") = $(basename "$i")
then
dummy=dummy
else
rm $i
fi
done
# Remove unwanted SVN stuff (TODO: avoid downloading it)
for i in "$target"/.svn "$target"/*/.svn
do
@ -144,12 +167,6 @@ do
fi
done
## No more : Add own libburn-README in toplevel
# cp -a "$changes"/README "$target"
## No more : Add modified Makefile.am
# cp -a "$changes"/Makefile.am "$target"
# Make SVN state tarball for the libburn team
tar czf "$cdrskin_tarball_svn" "$target"
@ -179,18 +196,20 @@ done
# Pack it up to the new libburn+cdrskin-tarball
tar czf "$cdrskin_tarball" "$target"
# Produce a static and a dynamic binary
# Produce a static and a dynamic binary, and a HTML man page
(
cd "$compile_dir" || exit 1
./configure
make
$compile_cmd -do_strip
"$compile_cmd" -do_strip
cp "$compile_result" "../$bintarget_dynamic"
if test -n "$compile_static_opts"
then
$compile_cmd $compile_static_opts -do_strip
"$compile_cmd" $compile_static_opts -do_strip
cp "$compile_result" "../$bintarget_static"
fi
"$man_to_html_cmd"
mv "$man_page_html" ..
)
# Remove the build area
@ -203,4 +222,5 @@ rm -rf "$target"
ls -l "$cdrskin_tarball"
ls -l "$bintarget_dynamic"
ls -l "$bintarget_static"
ls -l $(basename "$man_page_html")

View File

@ -20,26 +20,30 @@ set -x
# The script is to be run in the directory above the toplevel
# directory of libburn resp. cdrskin development.
#
# libburn version used: http://libburn.pykix.org
# The top level directory in the SVN snapshot is named
intermediate="./libburn_pykix"
# libburn source used: http://libburnia.pykix.org
# Downloaded by:
# $ svn co http://libburn-svn.pykix.org/libburn/trunk libburn_pykix
# $ svn co http://libburnia-svn.pykix.org/libburn/tags/... $intermediate
# packed up in a tarball just to save it from inadverted changes by
# $ tar czf libburn_svn.tgz libburn_pykix
# $ tar czf libburn_svn.tgz $intermediate
original="./libburn_svn.tgz"
# Historic moments:
# original="./libburn_svn_A60815.tgz"
# original="./libburn_cdrskin_A60819.tgz"
# The top level directory in that snapshot is named
intermediate="./libburn_pykix"
# My changes are in libburn-0.2.3.ts.develop , mainly in ./cdrskin
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-develop"
changes="./libburn-0.2.3.ts.develop"
skin_rev="0.2.7"
skin_release="0.3.3"
patch_level=""
skin_rev="$skin_release""$patch_level"
# The result directory and the name of the result tarballs
target="./cdrskin-${skin_rev}"
target="./cdrskin-${skin_release}"
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz"
@ -123,10 +127,7 @@ do
fi
done
# Remove automatically generated HTML man page
rm "$cdrskin_target"/man_1_cdrskin.html
# Remove eventual SVN stuff from cdrskin driectory
# Remove eventual SVN stuff from cdrskin directory
for i in .deps .dirstamp .libs
do
if test -e "$cdrskin_target"/"$i"
@ -138,6 +139,20 @@ done
# Remove GIFs of cdrskin_eng.html
rm "$cdrskin_target"/doener_*.gif
# Remove automatically generated HTML man page
rm "$cdrskin_target"/man_1_cdrskin.html
# Remove all add_ts_changes_to_libburn besides this one
for i in "$cdrskin_target"/add_ts_changes_to_libburn*
do
if test $(basename "$0") = $(basename "$i")
then
dummy=dummy
else
rm $i
fi
done
# Remove unwanted SVN stuff (TODO: avoid downloading it)
for i in "$target"/.svn "$target"/*/.svn
do
@ -152,12 +167,6 @@ do
fi
done
## No more : Add own libburn-README in toplevel
# cp -a "$changes"/README "$target"
## No more : Add modified Makefile.am
# cp -a "$changes"/Makefile.am "$target"
# Make SVN state tarball for the libburn team
tar czf "$cdrskin_tarball_svn" "$target"

View File

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH CDRSKIN 1 "January 12, 2007"
.TH CDRSKIN 1 "February 8, 2007"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -16,8 +16,8 @@
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
cdrskin \- burns preformatted data to CD-R, CD-RW, DVD+/-RW, DVD-RAM
via libburn.
cdrskin \- burns preformatted data to CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW,
DVD-RAM via libburn.
.SH SYNOPSIS
.B cdrskin
.RI [ options | track_source_addresses ]
@ -29,12 +29,12 @@ via libburn.
.\" respectively.
.PP
\fBcdrskin\fP is a program that provides some of cdrecord's options
in a compatible way for CD media. With DVD it has its own ways for now.
in a compatible way for CD media. With DVD it has its own ways.
You do not need to be superuser for its daily usage.
.PP
.B Overview of features:
.br
Blanking of CD-RW.
Blanking of CD-RW and DVD-RW.
.br
Burning of data or audio tracks to CD,
.br
@ -42,12 +42,16 @@ either in versatile Track at Once mode (TAO)
.br
or in Session at Once mode for seamless tracks.
.br
Multi session on CD (follow-up sessions in TAO only).
Multi session on CD (follow-up sessions in TAO only)
.br
and on DVD-RW or DVD-R (in Incremental write mode only).
.br
Single session on DVD-RW or DVD-R (Disk-at-once)
.br
or on overwriteable DVD+RW, DVD-RW, DVD-RAM.
.br
Bus scan, burnfree, speed options, retrieving media info, padding, fifo.
.br
Burning of a single data track to DVD+RW, DVD-RW or DVD-RAM.
.br
See section EXAMPLES at the end of this text.
.PP
.B Track recording model:
@ -64,7 +68,7 @@ More than one track can be burned by a single run of cdrskin.
In the terms of the MMC standard all tracks written by the same run constitute
a \fBsession\fP.
.br
CDs can be kept appendable so that further tracks can
Some media types can be kept appendable so that further tracks can
be written to them in subsequent runs of cdrskin (see option -multi).
Info about the addresses of burned tracks is kept in a table of
content (TOC) on media and can be retrieved via cdrskin option -toc.
@ -72,7 +76,7 @@ These informations are also used by the operating systems' CD-ROM read drivers.
.PP
In general there are two types of tracks: data and audio. They differ in
sector size, throughput and readability via the systems' CD-ROM drivers
resp. by music CD players.
resp. by music CD players. With DVD there is only type data.
.br
If not explicitely option -audio is given, then any track is burned as type
data, unless the track source is a file with suffix ".wav" or ".au" and has a
@ -96,7 +100,19 @@ the archivers afio and star. Not suitable seems GNU tar.
.br
CD-R can be initially written only once and eventually extended until they
get closed (or are spoiled because they are overly full). After that they are
read-only.
read-only. Closing is done automatically unless option
.B -multi
is given which keeps the media appendable.
.br
There are two write modes,
.B -tao
and
.B -sao .
.br
-tao allows to use track source of unpredictable length (like stdin) and allows
to write further sessions to appendable media. -sao produces audio sessions
with seamless tracks but needs predicted track sizes and cannot append sessions
to media.
.br
CD-RW media can be blanked to make them re-usable for another
round of overwriting. Usually
@ -106,24 +122,59 @@ Blanking damages the previous content but does not
make it completely unreadable. It is no effective privacy precaution.
Multiple cycles of blanking and overwriting with random numbers might be.
.PP
.B Recordable DVD Media:
.B Sequentially Recordable DVD Media:
.br
Currently only types DVD+RW, DVD-RW and DVD-RAM can be burned via cdrskin.
Currently only DVD-RW and DVD-R can be used for the Sequential recording model.
DVD-RW must be in state "Sequential Recording".
The media must be either blank or appendable.
Newly purchased DVD-RW and DVD-R media are in this state.
Used DVD-RW get into blank sequential state by option
.B blank=deformat_sequential .
.br
Incremental Streaming is the default write mode if it is offered by the media.
It may be selected explicitely by option
.B -tao
as it resembles much CD TAO by allowing track sources of
unpredicted length and to keep media appendable by option
.B -multi .
The only restriction towards CD-R[W] is the lack of support for -audio tracks.
Multiple tracks per session are permissible.
.br
The other write mode, DAO, has many restrictions. It does not work with
appendable media, allows no -multi and only a single track. The size of the
track needs to be known in advance. So either its source has to be a disk file
of recognizable size or the size has to be announced explicitely by options
.B tsize=
or
.B tao_to_sao_tsize= .
.br
DAO is the default mode for media which do not offer feature 21h Incremental
Streaming. It may also be selected explicitely by option
.B -sao .
.br
Program growisofs uses DAO on sequential DVD-R[W] media for maximum
DVD-ROM/-Video compatibility.
.PP
.B Overwriteable DVD Media:
.br
Currently only types DVD+RW, DVD-RW and DVD-RAM can be overwritten via cdrskin.
.br
DVD+RW and DVD-RAM media get treated as blank media regardless wether they
hold data or not. They need no special initial formatting.
Options -audio and -multi are not allowed. Only one track is allowed.
-toc does not return information about the media content.
Speed is counted in DVD units (i.e. 1x = 1,385,000 bytes/second). Currently
there is no difference between -sao and -tao. If ever, then -tao will be the
mode which preserves the current behavior.
Currently there is no difference between -sao and -tao. If ever, then -tao
will be the mode which preserves the current behavior.
.br
DVD-RW need to be formatted to state "Restricted Overwrite". Then they behave
much like DVD+RW. This formatting can be done by option
.B blank=format_overwrite
It is necessary for unused media, for media written or blanked by cdrecord,
for media which have been written unformatted by growisofs or blanked by
dvd+rw-format -blank. If in doubt, just give it a try.
DVD-RW are sold in state "Sequential Recording". To become suitable for the
Overwriteable DVD recording model they need to get formatted to state
"Restricted Overwrite". Then they behave much like DVD+RW. This formatting
can be done by option
.B blank=format_overwrite .
.br
Several programs like dvd+rw-format, cdrecord, wodim, or cdrskin option
blank=deformat_sequential can bring a DVD-RW out of overwriteable state so
that it has to be formatted again. If in doubt, just give it a try.
.PP
.B Drive preparation and addressing:
.br
@ -183,9 +234,11 @@ stereo. For little-endian byte order (which is usual on PCs) use option
.wav are examined wether they have a header in MS-WAVE format confirming
those parameters and eventually raw audio data get extracted and burned as
audio track. Same is done for suffix .au and SUN Audio.
.br
Option -audio may be used only with CD media and not with DVD.
.TP
.BI blank= type
Blank a CD-RW or format a DVD+/-RW.
Blank a CD-RW, a DVD-RW, or format a DVD+/-RW.
This is combinable with burning in the same run of cdrskin.
The type given with blank= selects the particular behavior:
.RS
@ -194,14 +247,17 @@ help
Print this list of blanking types.
.TP
all
Blank an entire CD.
Blank an entire CD-RW or an unformatted DVD-RW.
(See also --prodvd_cli_compatible)
.TP
fast
Minimally blank an entire CD.
Minimally blank an entire CD-RW or blank an unformatted DVD-RW.
(See also --prodvd_cli_compatible)
.TP
format_overwrite
Format a DVD-RW to "Restricted Overwrite". The user should bring some patience.
(Note: format_overwrite* are not original cdrecord options.)
.br
(Note: blank=format_overwrite* are not original cdrecord options.)
.TP
format_overwrite_quickest
Like format_overwrite without creating a 128 MB trailblazer session.
@ -215,8 +271,21 @@ rather than just 128 MB.
Most traditional formatting is attempted. No data get written.
Much patience is required.
.br
This option treats already formatted media even if not option -force is given.
.br
For DVD+RW this is the only supported explicit formatting type. It provides
complete "de-icing" so no reader slips on unwritten data areas.
.TP
deformat_sequential
Like blank=all but with the additional ability to blank overwriteable DVD-RW.
This will destroy their formatting and make them sequentially recordable.
.br
(Note: blank=deformat_sequential* are not original cdrecord options.)
.TP
deformat_sequential_quickest
Like blank=deformat_sequential but blanking DVD-RW only minimally.
This is faster than full blanking but may yield media incapable of
Incremental Streaming (-tao).
.RE
.TP
.BI \-checkdrive
@ -224,7 +293,8 @@ Retrieve some info about the addressed drive.
Exits with non-zero value if the drive cannot be found and opened.
.TP
.BI \-dao
Alias for option -sao. Write disk in Session at Once mode.
Alias for option -sao. Write CD in Session at Once mode
or DVD-R[W] in Disc-at-once mode.
.TP
.BI \-data
Subsequent tracks are data tracks. This option is default and only needed
@ -247,17 +317,18 @@ Be aware that deprecated option --old_pseudo_scsi_adr may change the meaning
of Bus,Target,Lun addresses.
.TP
.BI driveropts= opt
Set "driveropts=burnfree" to enable the drive's eventual protection mechanism
against temporary lack of source data (i.e. buffer underrun).
It is not an error to do this with a drive that has no such capabilities.
Set "driveropts=noburnfree" to disable the drive's eventual protection
mechanism against temporary lack of source data (i.e. buffer underrun).
A drive that announces no such capabilities will not get them enabled anyway,
even if attempted explicitely via "driveropts=burnfree".
.TP
.BI \-dummy
Try to perform the drive operations without actually affecting the inserted
media. There is no guarantee that this will work with a particular drive
in a particular write mode. Blanking is prevented reliably, though.
media. There is no guarantee that this will work with a particular combination
of drive, media, and write mode. Blanking is prevented reliably, though.
.TP
.BI \-eject
Eject the disk after work is done.
Eject the disc after work is done.
.TP
.BI \-force
Assume that the user knows better in situations when cdrskin or libburn are
@ -307,11 +378,15 @@ start address of the next session to be appended. The string is empty if
the most recent session was not written with option -multi.
.TP
.BI \-multi
This option keeps the CD appendable after the current session has been written.
Without it the disk gets closed and may not be written any more - unless it
is a CD-RW and gets blanked which causes loss of its content.
This option keeps the CD or unformatted DVD-R[W] appendable after the current
session has been written.
Without it the disc gets closed and may not be written any more - unless it
is a -RW and gets blanked which causes loss of its content.
.br
The following sessions can only be written in -tao mode.
The following sessions can only be written in -tao mode. -multi is prohibited
with overwriteable DVD media and with DVD-R[W] DAO write mode.
Option --prodvd_cli_compatible eventually makes -multi tolerable but cannot
make it work.
.br
In order to have all filesystem content accessible, the eventual ISO-9660
filesystem of a follow-up
@ -337,18 +412,27 @@ gets reset to padsize=0 after that next track is written. It may be set
again before the next track argument. About size specifiers, see option fs=.
.TP
.BI \-raw96r
Write disk in RAW/RAW96R mode. This mode allows to put more payload bytes
Write CD in RAW/RAW96R mode. This mode allows to put more payload bytes
into a CD sector but obviously at the cost of error correction. It can only
be used for tracks of fixely predicted size. Some drives allow this mode but
then behave strange or even go bad for the next few attempts to burn a CD.
One should use it only if inavoidable.
.TP
.BI \-sao
Write disk in Session At Once mode. This mode is able to put several audio
tracks on CD without producing audible gaps between them. It can only
be used for tracks of fixely predicted size. This implies that track arguments
which depict stdin or named pipes need to be preceeded by option tsize= or
by option tao_to_sao_tsize=.
Write CD in Session At Once mode, resp. a sequential DVD-R[W] in Disc-at-once
(DAO) mode.
.br
With CD this mode is able to put several audio tracks on media without
producing audible gaps between them.
.br
With DVD-R[W] this mode can only write a single track.
No -multi is allowed with DVD-R[W] -sao.
.br
-sao can only be used for tracks of fixely predicted size. This implies that
track arguments which depict stdin or named pipes need to be preceeded by
option tsize= or by option tao_to_sao_tsize=.
.br
-sao cannot be used on appendable media.
.TP
.BI \-scanbus
Scan the system for drives. On Linux the drives at /dev/s* and at /dev/hd*
@ -365,7 +449,8 @@ Bus,Target,Lun Number) 'Vendor' 'Mode' 'Revision'
.TP
.BI speed= number
Set speed of drive. With data CD, 1x speed corresponds to a throughput of
150 kB/s. It is not an error to set a speed higher than is suitable for drive
150,000 bytes/second. With DVD, 1x = 1,385,000 bytes/second.
It is not an error to set a speed higher than is suitable for drive
and media. One should stay within a realistic speed range, though.
.TP
.BI \-swab
@ -377,13 +462,16 @@ Less guesswork is needed if track sources are in format MS-WAVE in a file with
suffix ".wav".
.TP
.BI \-tao
Write disk in Track At Once (TAO) mode. This mode can be used with track
sources of unpredictable size, like standard input or named pipes. It is
also the only mode that can be used for writing to appendable CD which
already hold data.
Write CD in Track At Once (TAO) mode, resp. sequential DVD-R[W] in Incremental
Streaming mode. This mode also applies pro-forma to overwriteable DVD media.
.br
Mode -tao can be used with track sources of unpredictable size, like standard
input or named pipes. It is also the only mode that can be used for writing
to appendable media which already hold data. With unformatted DVD-R[W] it is
the only mode which allows -multi.
.TP
.BI \-toc
Print the table of content (TOC) which describes the tracks recorded on CD.
Print the table of content (TOC) which describes the tracks recorded on disc.
The output contains all info from option -atip plus lines which begin with
"track:", the track number, the word "lba:" and a number which gives the
start address of the track. Addresses are counted in CD sectors which with
@ -416,7 +504,7 @@ About size specifiers, see option fs=.
If the track source does not deliver the predicted amount of bytes, the
remainder of the track is padded with zeros. This is not considered an error.
If on the other hand the track source delivers more than the announced bytes
then the track on CD gets truncated to the predicted size and cdrskin exits
then the track on media gets truncated to the predicted size and cdrskin exits
with non-zero value.
.TP
.BI \-v
@ -465,10 +553,10 @@ fifo_start_at= combine a quick burn start and a large savings buffer to
compensate for temporary lack of source data. At the beginning of burning,
the software protection against buffer underun is as weak as the size of
fifo_start_at= . So it is best if the drive offers hardware protection which
has to be enabled by driveropts=burnfree.
is enabled automatically if not driveropts=noburnfree is given.
.TP
.BI \--list_ignored_options
List all ignored cdrecord options. The --options cannot be used as addresses
List all ignored cdrecord options. The "-" options cannot be used as addresses
of track sources. No track source address may begin with a text equal to an
option which ends by "=". The list is ended by an empty line.
.TP
@ -476,8 +564,32 @@ option which ends by "=". The list is ended by an empty line.
Only if used as first command line argument this option prevents reading and
interpretation of eventual startup files. See section FILES below.
.TP
.BI \--prodvd_cli_compatible
Activates behavior modifications with some DVD situations which bring cdrskin
nearer to the behavior of cdrecord-ProDVD:
.br
Option -multi with unsuitable media is not an error but simply has no effect.
.br
Options blank=fast and blank=all deformat overwriteable DVD-RW media.
.br
Option blank=fast does indeed minmal blanking with DVD-RW. This may yield media
which can only do DAO but not Incremental Streaming.
.TP
.BI \--single_track
Accept only the last argument of the command line as track source address.
.TP
.BI tao_to_sao_tsize= size
Set an exact fixed size for the next track to be in effect only if the track
source cannot deliver a size prediction and no tsize= was specified and an
exact track size prediction is demanded by the write mode.
.br
This was the fallback from bad old times when cdrskin was unable to burn
in mode -tao . It came back with minimally blanked DVD-RW which allow no
Incremental Streaming (-tao) resp. with explicitly selected write mode -sao
for best DVD-ROM compatibility.
.br
If the track source delivers less bytes than announced then the missing ones
will be filled with zeros.
.TP
.BI write_start_address= byte_offset
Set the address on media where to start writing the track. With DVD+RW or
@ -547,8 +659,8 @@ On signals exit even if the drive is in busy state. This is not a very good
idea. You might end up with a stuck drive that refuses to hand out the media.
.TP
.BI \--no_blank_appendable
Refuse to blank appendable CD-RW. This is a feature that was once builtin with
libburn. No information available for what use case it was needed.
Refuse to blank appendable CD-RW or DVD-RW. This is a feature that was once
builtin with libburn. No information available for what use case it was needed.
.TP
.BI \--no_convert_fs_adr
Do only literal translations of dev=. This prevents cdrskin from test-opening
@ -565,16 +677,10 @@ Linux specific:
Use and report literal Bus,Target,Lun addresses rather than real SCSI and
pseudo ATA addresses. This method is outdated and was never compatible with
original cdrecord.
.TP
.BI tao_to_sao_tsize= size
Set an exact fixed size for the next track to be in effect only if the track
source cannot deliver a size prediction and no tsize= was specified.
This is the fallback from bad old times when cdrskin was unable to burn
in mode -tao.
.br
.SH EXAMPLES
.SS
.B Get an overview of drives:
.B Get an overview of drives and their addresses:
.br
cdrskin -scanbus
.br
@ -586,47 +692,49 @@ cdrskin --devices
.br
cdrskin dev=0,1,0 -checkdrive
.br
cdrskin dev=ATA:1,0,0 -atip
cdrskin dev=ATA:1,0,0 -v -atip
.br
cdrskin dev=/dev/hdc -toc
.SS
.B Make used CD-RW writable again:
.B Make used CD-RW or used unformatted DVD-RW writable again:
.br
cdrskin -v dev=/dev/sg1 blank=all -eject
cdrskin -v dev=/dev/sg1 blank=fast -eject
.br
cdrskin -v dev=/dev/dvd blank=fast -eject
cdrskin -v dev=/dev/dvd blank=all -eject
.SS
.B Format DVD-RW before first use with cdrskin:
.B Format DVD-RW to avoid need for blanking before re-use:
.br
cdrskin -v dev=/dev/sr0 blank=format_overwrite
.SS
.B Write ISO-9660 filesystem image:
.B De-format DVD-RW to make it capable of multi-session again:
.br
cdrskin -v dev=/dev/sr0 blank=deformat_sequential
.SS
.B Write ISO-9660 filesystem image as only one to blank or formatted media:
.br
cdrskin -v dev=/dev/hdc speed=12 fs=8m \\
.br
driveropts=burnfree -sao -eject \\
.br
padsize=300k my_image.iso
-sao -eject padsize=300k my_image.iso
.SS
.B Write compressed afio archive on-the-fly:
.br
find . | afio -oZ - | \\
.br
cdrskin -v dev=0,1,0 fs=32m speed=8 driveropts=burnfree \\
cdrskin -v dev=0,1,0 fs=32m speed=8 \\
.br
padsize=300k -tao -
-tao padsize=300k -
.SS
.B Write several sessions to the same CD:
.B Write several sessions to the same CD or DVD-R[W]:
.br
cdrskin dev=/dev/hdc padsize=300k -multi 1.iso
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso
.br
cdrskin dev=/dev/hdc padsize=300k -multi -tao 2.afio
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso
.br
cdrskin dev=/dev/hdc padsize=300k -multi -tao 3.afio
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso
.br
cdrskin dev=/dev/hdc padsize=300k -tao 4.afio
cdrskin dev=/dev/hdc -v padsize=300k -tao 4.iso
.SS
.B Get CD multi-session info for option -C of program mkisofs:
.B Get CD or DVD-R[W] multi-session info for option -C of program mkisofs:
.br
c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)
.br
@ -634,9 +742,7 @@ mkisofs ... -C "$c_values" ...
.SS
.B Write audio tracks to CD:
.br
cdrskin -v dev=ATA:1,0,0 speed=48 \\
.br
driveropts=burnfree -sao \\
cdrskin -v dev=ATA:1,0,0 speed=48 -sao \\
.br
track1.wav track2.au -audio -swab track3.raw
.br
@ -691,7 +797,7 @@ Other CD/DVD burn programs:
.BR wodim (1)
.br
.TP
For DVD burning:
For DVD burning (also tutor of libburn's DVD capabilities):
.br
.BR growisofs (1)
.br

View File

@ -7,7 +7,7 @@ A cdrecord compatible command line interface for libburn.
This project is neither directed against original cdrecord nor does it exploit
any source code of said program. It rather tries to be an alternative method
to burn CD which is not based on the same code as cdrecord.
to burn CD or DVD, which is not based on the same code as cdrecord.
See also : http://scdbackup.sourceforge.net/cdrskin_eng.html
Interested users of cdrecord are encouraged to contribute further option
@ -33,48 +33,10 @@ The implementation of an option would probably consist of
See option blank= for an example.
------------------------------------------------------------------------------
About compliance with *strong urge* of API towards burn_drive_scan_and_grab()
For a more comprehensive example of the advised way to behave with libburn
see test/libburner.c .
For a more comprehensive example of the advised way to write an application
of libburn see test/libburner.c .
cdrskin was the initiator of the whitelist functionality within libburn.
Now it has problems to obviously comply with the new API best practice
presciptions literally. Therefore this explanation:
On start it restricts the library to a single drive if it already knows the
persistent address by option dev= . This is done with a combination of
burn_drive_add_whitelist() and burn_drive_scan(). Not compliant to the
literal strong urge but in fact exactly fulfilling the reason for that
urge in the API: any scanned drive might be opened exclusively after
burn_drive_scan(). It is kernel dependent wether this behavior is on, off
or switchable. The sysdamin will want it on - but only for one drive.
So with dev=... cdrskin complies to the spirit of the strong urge.
Without dev=... it has to leave out the whitelist in order to enable bus
scanning and implicit drive address 0. A tradition of 9 months shall not
be broken. So burns without dev= will stay possible - but harmless only
on single drive systems.
Burns without dev= resp. with dev=number are harmless on multi-drive systems.
This is because Cdrskin_grab_drive() either drops the unwanted drives or
it enforces a restart of the library with the desired drive's persistent
address. This restart then really uses the strongly urged function
burn_drive_scan_and_grab().
Thus, cdrskin complies with the new spirit of API by closing down libburn
or by dropping unused drives as soon as the persistent drive address is
known and the drive is to be used with a long running operation. To my
knowlege all long running operations in cdrskin need a grabbed drive.
This spaghetti approach seems necessary to keep small the impact of new API
urge on cdrskin's stability. cdrskin suffers from having donated the body
parts which have been transplanted to libburn in order to create
burn_drive_scan_and_grab() . The desired sysadmin friendlyness was already
achieved by most cdrskin runs. The remaining problem situations should now
be defused by releasing any short time grabbed flocks of drives during the
restart of libburn.
------------------------------------------------------------------------------
This program is currently copyright Thomas Schmitt only.
The copyrights of several components of libburnia.pykix.org are willfully
@ -124,7 +86,7 @@ or
/** The official program version */
#ifndef Cdrskin_prog_versioN
#define Cdrskin_prog_versioN "0.2.7"
#define Cdrskin_prog_versioN "0.3.2"
#endif
/** The source code release timestamp */
@ -157,25 +119,24 @@ or
#endif /* Cdrskin_libburn_cvs_A60220_tS */
#ifdef Cdrskin_libburn_0_2_6
#define Cdrskin_libburn_versioN "0.2.6"
#ifdef Cdrskin_libburn_0_3_2
#define Cdrskin_libburn_versioN "0.3.2"
#define Cdrskin_libburn_from_pykix_svN 1
#endif /* Cdrskin_libburn_0_2_6 */
#endif /* Cdrskin_libburn_0_3_2 */
#ifdef Cdrskin_libburn_0_2_7
#define Cdrskin_libburn_versioN "0.2.7"
#ifdef Cdrskin_libburn_0_3_3
#define Cdrskin_libburn_versioN "0.3.3"
#define Cdrskin_libburn_from_pykix_svN 1
#define Cdrskin_atip_speed_is_oK 1
#define Cdrskin_no_aftergrab_loopS 1
#define Cdrskin_libburn_has_get_profilE 1
#define Cdrskin_libburn_has_set_start_bytE 1
#define Cdrskin_libburn_has_wrote_welL 1
#define Cdrskin_libburn_has_bd_formattinG 1
#define Cdrskin_libburn_has_burn_disc_formaT 1
#endif /* Cdrskin_libburn_0_2_7 */
/* Place novelty switch macros here.
Move them down to Cdrskin_libburn_from_pykix_svN on version leap
*/
/* no novelties yet */
#endif /* Cdrskin_libburn_0_3_3 */
#ifndef Cdrskin_libburn_versioN
#define Cdrskin_libburn_versioN "0.2.6"
#define Cdrskin_libburn_versioN "0.3.2"
#define Cdrskin_libburn_from_pykix_svN 1
#endif
@ -202,6 +163,15 @@ or
#define Cdrskin_libburn_has_pretend_fulL 1
#define Cdrskin_libburn_has_multI 1
#define Cdrskin_libburn_has_buffer_min_filL 1
#define Cdrskin_atip_speed_is_oK 1
#define Cdrskin_libburn_has_get_profilE 1
#define Cdrskin_libburn_has_set_start_bytE 1
#define Cdrskin_libburn_has_wrote_welL 1
#define Cdrskin_libburn_has_bd_formattinG 1
#define Cdrskin_libburn_has_burn_disc_formaT 1
#define Cdrskin_libburn_has_get_msc1 1
#define Cdrskin_libburn_has_toc_entry_extensionS 1
#define Cdrskin_libburn_has_get_multi_capS 1
#ifdef Cdrskin_new_api_tesT
@ -776,6 +746,7 @@ struct CdrtracK {
int source_fd;
int is_from_stdin;
double fixed_size;
double tao_to_sao_tsize;
double padding;
int set_by_padsize;
int sector_pad_up; /* enforce single sector padding */
@ -828,10 +799,10 @@ int Cdrtrack_new(struct CdrtracK **track, struct CdrskiN *boss,
struct CdrtracK *o;
int ret,skin_track_type;
int Cdrskin_get_source(struct CdrskiN *skin, char *source_path,
double *fixed_size, double *padding,
int *set_by_padsize, int *track_type,
int *track_type_by_default, int *swap_audio_bytes,
int flag);
double *fixed_size, double *tao_to_sao_tsize,
double *padding, int *set_by_padsize,
int *track_type, int *track_type_by_default,
int *swap_audio_bytes, int flag);
int Cdrskin_get_fifo_par(struct CdrskiN *skin, int *fifo_enabled,
int *fifo_size, int *fifo_start_at, int flag);
@ -844,6 +815,7 @@ int Cdrtrack_new(struct CdrtracK **track, struct CdrskiN *boss,
o->source_fd= -1;
o->is_from_stdin= !!(flag&2);
o->fixed_size= 0.0;
o->tao_to_sao_tsize= 0.0;
o->padding= 0.0;
o->set_by_padsize= 0;
o->sector_pad_up= Cdrskin_all_tracks_with_sector_paD;
@ -860,7 +832,8 @@ int Cdrtrack_new(struct CdrtracK **track, struct CdrskiN *boss,
o->ff_fifo= NULL;
o->ff_idx= -1;
o->libburn_track= NULL;
ret= Cdrskin_get_source(boss,o->source_path,&(o->fixed_size),&(o->padding),
ret= Cdrskin_get_source(boss,o->source_path,&(o->fixed_size),
&(o->tao_to_sao_tsize),&(o->padding),
&(o->set_by_padsize),&(skin_track_type),
&(o->track_type_by_default),&(o->swap_audio_bytes),
0);
@ -933,6 +906,7 @@ int Cdrtrack_get_track_type(struct CdrtracK *o, int *track_type,
rather than the predicted fixed_size (if available).
padding returns the difference from number of written
bytes.
bit1= size returns fixed_size, padding returns tao_to_sao_tsize
*/
int Cdrtrack_get_size(struct CdrtracK *track, double *size, double *padding,
double *sector_size, int flag)
@ -951,7 +925,8 @@ int Cdrtrack_get_size(struct CdrtracK *track, double *size, double *padding,
fprintf(stderr,"cdrskin_debug: sizeof(off_t)=%d\n",
sizeof(off_t));
*/
}
} else if(flag&2)
*padding= track->tao_to_sao_tsize;
#endif
*sector_size= track->sector_size;
@ -1324,6 +1299,14 @@ flag:
}
int Cdrtrack_activate_tao_tsize(struct CdrtracK *track, int flag)
{
if(track->fixed_size<=0.0)
track->fixed_size= track->tao_to_sao_tsize;
return(track->fixed_size>0.0);
}
#ifndef Cdrskin_extra_leaN
/** Try to read bytes from the track's fifo outlet and eventually discard
@ -1834,6 +1817,10 @@ return:
"\tformat_overwrite_quickest\tto \"Restricted Overwrite intermediate\"\n");
fprintf(stderr,
"\tformat_overwrite_full\tfull-size format a DVD-RW or DVD+RW\n");
fprintf(stderr,
"\tdeformat_sequential\tfully blank, even formatted DVD-RW\n");
fprintf(stderr,
"\tdeformat_sequential_quickest\tminimally blank, even DVD-RW\n");
#else /* ! Cdrskin_extra_leaN */
@ -2029,6 +2016,8 @@ set_dev:;
" --no_rc as first argument: do not read startup files\n");
printf(" --old_pseudo_scsi_adr use and report literal Bus,Target,Lun\n");
printf(" rather than real SCSI and pseudo ATA.\n");
printf(" --prodvd_cli_compatible react on some DVD types more like\n");
printf(" cdrecord-ProDVD with blank= and -multi\n");
printf(
" --single_track accept only last argument as source_address\n");
@ -2366,6 +2355,7 @@ struct CdrskiN {
int dummy_mode;
int force_is_set;
int single_track;
int prodvd_cli_compatible;
int do_devices;
@ -2389,7 +2379,7 @@ struct CdrskiN {
bit8 = write zeros after formatting
bit9 = insist in size 0
bit10= format to maximum available size
2=format_sequential (unimplemented yet)
2=deformat_sequential (blank_fast might matter)
*/
double blank_format_size; /* to be used with burn_disc_format() */
@ -2505,6 +2495,7 @@ int Cdrskin_new(struct CdrskiN **skin, struct CdrpreskiN *preskin, int flag)
o->dummy_mode= 0;
o->force_is_set= 0;
o->single_track= 0;
o->prodvd_cli_compatible= 0;
o->do_devices= 0;
o->do_scanbus= 0;
o->do_checkdrive= 0;
@ -2522,7 +2513,7 @@ int Cdrskin_new(struct CdrskiN **skin, struct CdrpreskiN *preskin, int flag)
o->block_type= BURN_BLOCK_SAO;
o->multi= 0;
o->write_start_address= -1.0;
o->burnfree= 0;
o->burnfree= 1;
o->do_eject= 0;
o->eject_device[0]= 0;
o->source_path[0]= 0;
@ -2609,13 +2600,14 @@ int Cdrskin_set_msinfo_fd(struct CdrskiN *skin, int result_fd, int flag)
/** Return information about current track source */
int Cdrskin_get_source(struct CdrskiN *skin, char *source_path,
double *fixed_size, double *padding,
int *set_by_padsize, int *track_type,
int *track_type_by_default, int *swap_audio_bytes,
int flag)
double *fixed_size, double *tao_to_sao_tsize,
double *padding, int *set_by_padsize,
int *track_type, int *track_type_by_default,
int *swap_audio_bytes, int flag)
{
strcpy(source_path,skin->source_path);
*fixed_size= skin->fixed_size;
*tao_to_sao_tsize = skin->tao_to_sao_tsize;
*padding= skin->padding;
*set_by_padsize= skin->set_by_padsize;
*track_type= skin->track_type;
@ -3512,7 +3504,7 @@ int Cdrskin_msinfo(struct CdrskiN *skin, int flag)
enum burn_disc_status s;
struct burn_drive *drive;
struct burn_disc *disc= NULL;
struct burn_session **sessions;
struct burn_session **sessions= NULL;
struct burn_track **tracks;
struct burn_toc_entry toc_entry;
@ -3520,24 +3512,22 @@ int Cdrskin_msinfo(struct CdrskiN *skin, int flag)
if(ret<=0)
return(ret);
drive= skin->drives[skin->driveno].drive;
#ifndef Cdrskin_no_aftergrab_loopS
while(burn_drive_get_status(drive,NULL) != BURN_DRIVE_IDLE)
usleep(100002);
while ((s= burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
usleep(100002);
#else
s= burn_disc_get_status(drive);
#endif /* ! Cdrskin_no_aftergrab_loopS */
if(s!=BURN_DISC_APPENDABLE) {
Cdrskin_report_disc_status(skin,s,0);
fprintf(stderr,
"cdrskin: FATAL : -msinfo can only operate on appendable (i.e. -multi) CD\n");
fprintf(stderr,"cdrskin: FATAL : -msinfo can only operate on appendable (i.e. -multi) discs\n");
{ret= 0; goto ex;}
}
disc= burn_drive_get_disc(drive);
if(disc==NULL) {
#ifdef Cdrskin_libburn_has_get_msc1
/* No TOC available. Try to inquire directly. */
ret= burn_disc_get_msc1(drive,&lba);
if(ret>0)
goto obtain_nwa;
#endif /* Cdrskin_libburn_has_get_msc1 */
fprintf(stderr,"cdrskin: FATAL : Cannot obtain info about CD content\n");
{ret= 0; goto ex;}
}
@ -3547,19 +3537,42 @@ int Cdrskin_msinfo(struct CdrskiN *skin, int flag)
if(tracks==NULL || num_tracks<=0)
continue;
burn_track_get_entry(tracks[0],&toc_entry);
lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
#ifdef Cdrskin_libburn_has_toc_entry_extensionS
if(toc_entry.extensions_valid&1) { /* DVD extension valid */
lba= toc_entry.start_lba;
} else {
#else
{
#endif
lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
}
}
if(lba==-123456789) {
fprintf(stderr,"cdrskin: FATAL : Cannot find any track on CD\n");
{ret= 0; goto ex;}
}
obtain_nwa:;
ret= Cdrskin_obtain_nwa(skin,&nwa,flag);
if(ret<=0) {
if (sessions == NULL) {
fprintf(stderr,
"cdrskin: SORRY : Cannot obtain next writeable address\n");
{ret= 0; goto ex;}
}
fprintf(stderr,
"cdrskin: NOTE : Guessing next writeable address from leadout\n");
burn_session_get_leadout_entry(sessions[num_sessions-1],&toc_entry);
aux_lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
#ifdef Cdrskin_libburn_has_toc_entry_extensionS
if(toc_entry.extensions_valid&1) { /* DVD extension valid */
aux_lba= toc_entry.start_lba;
} else {
#else
{
#endif
aux_lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
}
if(num_sessions>0)
nwa= aux_lba+6900;
else
@ -3607,7 +3620,7 @@ ex:;
int Cdrskin_toc(struct CdrskiN *skin, int flag)
{
int num_sessions= 0,num_tracks= 0,lba= 0,track_count= 0,total_tracks= 0;
int session_no, track_no;
int session_no, track_no, pmin, psec, pframe;
struct burn_drive *drive;
struct burn_disc *disc= NULL;
struct burn_session **sessions;
@ -3636,11 +3649,26 @@ int Cdrskin_toc(struct CdrskiN *skin, int flag)
for(track_no= 0; track_no<num_tracks; track_no++) {
track_count++;
burn_track_get_entry(tracks[track_no], &toc_entry);
lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
#ifdef Cdrskin_libburn_has_toc_entry_extensionS
if(toc_entry.extensions_valid&1) { /* DVD extension valid */
lba= toc_entry.start_lba;
burn_lba_to_msf(lba, &pmin, &psec, &pframe);
} else {
#else
{
#endif
pmin= toc_entry.pmin;
psec= toc_entry.psec;
pframe= toc_entry.pframe;
lba= burn_msf_to_lba(pmin,psec,pframe);
}
if(track_no==0 && burn_session_get_hidefirst(sessions[session_no]))
printf("cdrskin: NOTE : first track is marked as \"hidden\".\n");
printf("track: %2d lba: %9d (%9d) %2.2u:%2.2u:%2.2u",track_count,
lba,4*lba,toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
printf("track: %2d lba: %9d (%9d) %2.2d:%2.2d:%2.2d",track_count,
lba,4*lba,pmin,psec,pframe);
printf(" adr: %d control: %d",toc_entry.adr,toc_entry.control);
/* >>> From where does cdrecord take "mode" ? */
@ -3655,9 +3683,23 @@ int Cdrskin_toc(struct CdrskiN *skin, int flag)
if((flag&1) && session_no<num_sessions-1)
continue;
burn_session_get_leadout_entry(sessions[session_no],&toc_entry);
lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
printf("track:lout lba: %9d (%9d) %2.2u:%2.2u:%2.2u",
lba,4*lba,toc_entry.pmin,toc_entry.psec,toc_entry.pframe);
#ifdef Cdrskin_libburn_has_toc_entry_extensionS
if(toc_entry.extensions_valid&1) { /* DVD extension valid */
lba= toc_entry.start_lba;
burn_lba_to_msf(lba, &pmin, &psec, &pframe);
} else {
#else
{
#endif
pmin= toc_entry.pmin;
psec= toc_entry.psec;
pframe= toc_entry.pframe;
lba= burn_msf_to_lba(pmin,psec,pframe);
}
printf("track:lout lba: %9d (%9d) %2.2d:%2.2d:%2.2d",
lba,4*lba,pmin,psec,pframe);
printf(" adr: %d control: %d",toc_entry.adr,toc_entry.control);
printf(" mode: -1\n");
}
@ -3690,16 +3732,7 @@ int Cdrskin_atip(struct CdrskiN *skin, int flag)
if(ret<=0)
return(ret);
drive= skin->drives[skin->driveno].drive;
#ifndef Cdrskin_no_aftergrab_loopS
while(burn_drive_get_status(drive,NULL) != BURN_DRIVE_IDLE)
usleep(100002);
while ((s= burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
usleep(100002);
#else
s= burn_disc_get_status(drive);
#endif
Cdrskin_report_disc_status(skin,s,0);
if(s==BURN_DISC_APPENDABLE && skin->no_blank_appendable) {
is_not_really_erasable= 1;
@ -3919,10 +3952,10 @@ int Cdrskin_blank(struct CdrskiN *skin, int flag)
int ret,loop_counter= 0,hint_force= 0,do_format= 0, profile_number= -1;
int wrote_well= 1;
double start_time;
char *verb= "format", *presperf="blanking", *fmt_text= "format_...";
char *verb= "blank", *presperf="blanking", *fmt_text= "...";
char profile_name[80];
static char fmtp[][40]= {
"format_default", "format_overwrite", "format_sequential"};
"format_default", "format_overwrite", "deformat_sequential"};
static int fmtp_max= 2;
start_time= Sfile_microtime(0); /* will be refreshed later */
@ -3930,16 +3963,7 @@ int Cdrskin_blank(struct CdrskiN *skin, int flag)
if(ret<=0)
return(ret);
drive= skin->drives[skin->driveno].drive;
#ifndef Cdrskin_no_aftergrab_loopS
while(burn_drive_get_status(drive,NULL) != BURN_DRIVE_IDLE)
usleep(100002);
while ((s= burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
usleep(100002);
#else
s= burn_disc_get_status(drive);
#endif
profile_name[0]= 0;
#ifdef Cdrskin_libburn_has_get_profilE
if(skin->grabbed_drive)
@ -3949,7 +3973,7 @@ int Cdrskin_blank(struct CdrskiN *skin, int flag)
if(skin->verbosity>=Cdrskin_verbose_progresS)
Cdrskin_report_disc_status(skin,s,0);
do_format= skin->blank_format_type & 0xff;
if(do_format) {
if(do_format == 1) {
verb= "format";
presperf= "formatting";
}
@ -3957,8 +3981,7 @@ int Cdrskin_blank(struct CdrskiN *skin, int flag)
#ifdef Cdrskin_libburn_has_pretend_fulL
if(s==BURN_DISC_UNSUITABLE) {
if(skin->force_is_set) {
fprintf(stderr,
"cdrskin: NOTE : -force blank=... : Treating unsuitable media as burn_disc_full\n");
fprintf(stderr,"cdrskin: NOTE : -force blank=... : Treating unsuitable media as burn_disc_full\n");
ret= burn_disc_pretend_full(drive);
s= burn_disc_get_status(drive);
} else
@ -3966,29 +3989,24 @@ int Cdrskin_blank(struct CdrskiN *skin, int flag)
}
#endif /* Cdrskin_libburn_has_pretend_fulL */
if(do_format) {
if(do_format)
if(do_format>=0 && do_format<=fmtp_max)
fmt_text= fmtp[do_format];
if(do_format!=1) {
/* >>> other formats to come. At least _sequential */;
if(do_format==2) {
/* Forceful blanking to Sequential Recording for DVD-R[W] and CD-RW */
fprintf(stderr,
"cdrskin: SORRY : only blank=%s is implemented yet\n",fmtp[1]);
return(0);
} else if(profile_number == 0x14) { /* DVD-RW sequential */
if(do_format!=1)
goto unsupported_format_type;
} else if(profile_number == 0x13) { /* DVD-RW restricted overwrite */
if(do_format==1 && skin->force_is_set) {
if(!(profile_number == 0x14 || profile_number == 0x13 ||
profile_number == 0x0a))
goto unsupported_format_type;
} else if (do_format==1) {
/* Formatting to become overwriteable for DVD-RW and DVD+RW */
if(profile_number == 0x14) { /* DVD-RW sequential */
/* ok */;
} else if(do_format!=1) {
unsupported_format_type:;
fprintf(stderr,
"cdrskin: SORRY : blank=%s : unsupported format and/or media type\n",
fmt_text);
return(0);
} else {
} else if(profile_number == 0x13) { /* DVD-RW restricted overwrite */
if(!(skin->force_is_set || ((skin->blank_format_type>>8)&4))) {
fprintf(stderr,
"cdrskin: NOTE : blank=format_... : media is already formatted\n");
fprintf(stderr,
@ -3996,15 +4014,11 @@ unsupported_format_type:;
return(2);
}
} else if(profile_number == 0x1a) { /* DVD+RW */
if(do_format!=1)
goto unsupported_format_type;
if(!((skin->blank_format_type>>8)&4)) {
fprintf(stderr,
"cdrskin: NOTE : blank=format_... : DVD+RW do not need this\n");
fprintf(stderr,
"cdrskin: HINT : For de-icing use option blank=format_overwrite_full");
fprintf(stderr,
"cdrskin: HINT : If you really want to re-format, add option -force\n");
return(2);
}
} else {
@ -4017,10 +4031,12 @@ unsupported_format_type:;
"cdrskin: NOTE : blank=%s accepted not yet suitable media\n",
fmt_text);
} else { /* do_format */
} else if(do_format==0) {
/* Classical blanking of erasable media */
if(s!=BURN_DISC_FULL &&
(s!=BURN_DISC_APPENDABLE || skin->no_blank_appendable)) {
(s!=BURN_DISC_APPENDABLE || skin->no_blank_appendable) &&
!(profile_number == 0x13 && skin->prodvd_cli_compatible)) {
Cdrskin_release_drive(skin,0);
if(s==BURN_DISC_BLANK) {
fprintf(stderr,
@ -4042,8 +4058,17 @@ unsupported_format_type:;
fprintf(stderr,"cdrskin: FATAL : blank=... : media is not erasable\n");
return(0);
}
if((profile_number == 0x14 || profile_number == 0x13) &&
!skin->prodvd_cli_compatible)
skin->blank_fast= 0; /* only with deformat_sequential_quickest */
} /* ! do_format */
} else {
unsupported_format_type:;
fprintf(stderr,
"cdrskin: SORRY : blank=%s is unsupported with media type %s\n",
fmt_text, profile_name);
return(0);
}
if(skin->dummy_mode) {
fprintf(stderr,
@ -4055,11 +4080,11 @@ unsupported_format_type:;
Cdrskin_adjust_speed(skin,0);
#ifndef Cdrskin_extra_leaN
Cdrskin_wait_before_action(skin,1+(!!do_format));
Cdrskin_wait_before_action(skin,1+(do_format==1));
#endif /* ! Cdrskin_extra_leaN */
skin->drive_is_busy= 1;
if(do_format==0) {
if(do_format==0 || do_format==2) {
burn_disc_erase(drive,skin->blank_fast);
#ifdef Cdrskin_libburn_has_burn_disc_formaT
@ -4069,10 +4094,6 @@ unsupported_format_type:;
#endif
} else {
/* >>> */;
/* <<< */
fprintf(stderr,"cdrskin: SORRY : Format type %d not implemented yet.\n",
do_format);
ret= 0; goto ex;
@ -4102,7 +4123,7 @@ blanking_done:;
fprintf(stderr,
"\rcdrskin: %s done \n",
presperf);
printf("%s time: %.3fs\n",(do_format?"Formatting":"Blanking"),
printf("%s time: %.3fs\n",(do_format==1?"Formatting":"Blanking"),
Sfile_microtime(0)-start_time);
}
fflush(stdout);
@ -4338,16 +4359,16 @@ thank_you_for_patience:;
Cdrfifo_get_counters(skin->fifo,&curr_fifo_in,&curr_fifo_out,0);
Cdrfifo_get_sizes(skin->fifo,&bs,&fs,0);
}
}
if(skin->fifo_size>0) {
sprintf(fifo_text,"(fifo %3d%%) ",fifo_percent);
if(skin->verbosity>=Cdrskin_verbose_debug_fifO) {
fprintf(stderr,
"\ncdrskin_debug: fifo >= %9d / %d : %8.f in, %8.f out\n",
fill,(int) buffer_size,
curr_fifo_in-last_fifo_in,curr_fifo_out-last_fifo_out);
last_fifo_in= curr_fifo_in;
last_fifo_out= curr_fifo_out;
if(skin->fifo_size>0) {
sprintf(fifo_text,"(fifo %3d%%) ",fifo_percent);
if(skin->verbosity>=Cdrskin_verbose_debug_fifO) {
fprintf(stderr,
"\ncdrskin_debug: fifo >= %9d / %d : %8.f in, %8.f out\n",
fill,(int) buffer_size,
curr_fifo_in-last_fifo_in,curr_fifo_out-last_fifo_out);
last_fifo_in= curr_fifo_in;
last_fifo_out= curr_fifo_out;
}
}
}
if(skin->supposed_track_idx >= 0 &&
@ -4435,9 +4456,14 @@ int Cdrskin_activate_write_mode(struct CdrskiN *skin, enum burn_disc_status s,
int flag)
{
int ok, was_still_default= 0, block_type_demand,track_type,sector_size, i;
int profile_number= -1;
int profile_number= -1, track_type_1= 0, mixed_mode= 0, unpredicted_size= 0;
int might_do_tao= 0, might_do_sao= 1, allows_multi= 1, ret;
struct burn_drive_info *drive_info = NULL;
char profile_name[80];
double fixed_size= 0.0, tao_to_sao_tsize= 0.0, dummy;
#ifdef Cdrskin_libburn_has_get_multi_capS
struct burn_multi_caps *caps = NULL;
#endif
profile_name[0]= 0;
#ifdef Cdrskin_libburn_has_get_profilE
@ -4445,15 +4471,53 @@ int Cdrskin_activate_write_mode(struct CdrskiN *skin, enum burn_disc_status s,
burn_disc_get_profile(skin->grabbed_drive,&profile_number,profile_name);
#endif
#ifdef Cdrskin_allow_libburn_taO
might_do_tao= 1;
#endif
#ifdef Cdrskin_libburn_has_get_multi_capS
ret = burn_disc_get_multi_caps(skin->grabbed_drive,BURN_WRITE_NONE,&caps,0);
if (ret<0) {
fprintf(stderr,
"cdrskin: FATAL : Cannot obtain write mode capabilities of drive\n");
return(0);
} else if(ret==0) {
fprintf(stderr,
"cdrskin: SORRY : Cannot find any suitable write mode for this media\n");
burn_disc_free_multi_caps(&caps);
return(0);
}
might_do_tao= caps->might_do_tao;
might_do_sao= caps->might_do_sao;
burn_disc_free_multi_caps(&caps);
#endif
for(i=0;i<skin->track_counter;i++) {
Cdrtrack_get_track_type(skin->tracklist[i],&track_type,&sector_size,0);
if(i==0)
track_type_1= track_type;
else if(track_type_1!=track_type)
mixed_mode= 1;
Cdrtrack_get_size(skin->tracklist[i],&fixed_size,
&tao_to_sao_tsize,&dummy,2);
if(fixed_size<=0)
unpredicted_size= 1+(tao_to_sao_tsize<=0);
}
if(strcmp(skin->preskin->write_mode_name,"DEFAULT")==0) {
was_still_default= 1;
if(s == BURN_DISC_APPENDABLE) {
if((s == BURN_DISC_APPENDABLE || mixed_mode) && might_do_tao) {
strcpy(skin->preskin->write_mode_name,"TAO");
was_still_default= 2; /*<<< prevents trying of SAO if drive dislikes TAO*/
} else if(profile_number==0x1a || profile_number==0x13 ||
profile_number==0x12) {
/* DVD+RW , DVD-RW Restricted Overwrite , DVD-RAM */
was_still_default= 2; /* prevents trying of SAO if drive dislikes TAO*/
} else if(unpredicted_size && might_do_tao) {
strcpy(skin->preskin->write_mode_name,"TAO");
if(unpredicted_size>1)
was_still_default= 2; /* prevents trying of SAO */
} else if((profile_number==0x1a || profile_number==0x13 ||
profile_number==0x12 ||
profile_number==0x11 || profile_number==0x14)
&& might_do_tao) {
/* DVD+RW, DVD-RW Restr. Overwrite, DVD-RAM, DVD-R, DVD-RW Sequential */
strcpy(skin->preskin->write_mode_name,"TAO");
} else {
strcpy(skin->preskin->write_mode_name,"SAO");
@ -4465,7 +4529,6 @@ int Cdrskin_activate_write_mode(struct CdrskiN *skin, enum burn_disc_status s,
#ifdef Cdrskin_allow_libburn_taO
} else if(strcmp(skin->preskin->write_mode_name,"TAO")==0) {
strcpy(skin->preskin->write_mode_name,"TAO");
skin->write_type= BURN_WRITE_TAO;
skin->block_type= BURN_BLOCK_MODE1;
#endif /* Cdrskin_allow_libburn_taO */
@ -4495,10 +4558,14 @@ check_with_drive:;
/* >>> drive_info does not reflect DVD capabilities yet */
ok= 1;
ok= 0;
if(skin->write_type==BURN_WRITE_SAO && might_do_sao)
ok= 1;
if(skin->write_type==BURN_WRITE_TAO && might_do_tao)
ok= 1;
} else if(skin->write_type==BURN_WRITE_RAW)
ok= !!(drive_info->raw_block_types & BURN_BLOCK_RAW96R);
else if(skin->write_type==BURN_WRITE_SAO)
else if(skin->write_type==BURN_WRITE_SAO && !mixed_mode)
ok= !!(drive_info->sao_block_types & BURN_BLOCK_SAO);
else if(skin->write_type==BURN_WRITE_TAO) {
block_type_demand= 0;
@ -4512,6 +4579,24 @@ check_with_drive:;
ok= ((drive_info->tao_block_types & block_type_demand)==block_type_demand);
}
if(skin->write_type==BURN_WRITE_SAO && mixed_mode) {
fprintf(stderr,
"cdrskin: FATAL : Cannot write mix of data and audio in SAO mode\n");
if(might_do_tao)
fprintf(stderr,
"cdrskin: HINT : Try with option -tao resp. without -sao\n");
return(0);
}
if(skin->write_type==BURN_WRITE_SAO && unpredicted_size>1) {
fprintf(stderr,
"cdrskin: FATAL : At least one track has no predictable size.\n");
fprintf(stderr,
"cdrskin: HINT : Use tsize= or tao_to_sao_tsize= to announce the track size\n");
if(might_do_tao)
fprintf(stderr,
"cdrskin: HINT : or try with option -tao resp. without -sao\n");
return(0);
}
if(!ok) {
fprintf(stderr,
"cdrskin: %s : Drive indicated refusal for write mode %s.\n",
@ -4519,24 +4604,55 @@ check_with_drive:;
skin->preskin->write_mode_name);
if(! skin->force_is_set) {
if(was_still_default==1) {
if(skin->write_type==BURN_WRITE_RAW ||
skin->write_type==BURN_WRITE_SAO) {
was_still_default= 2; /* do not try more than once */
if((skin->write_type==BURN_WRITE_RAW ||
skin->write_type==BURN_WRITE_SAO) && might_do_tao) {
skin->write_type= BURN_WRITE_TAO;
skin->block_type= BURN_BLOCK_MODE1;
strcpy(skin->preskin->write_mode_name,"TAO");
} else {
goto check_with_drive;
} else if (might_do_sao) {
skin->write_type= BURN_WRITE_SAO;
skin->block_type= BURN_BLOCK_SAO;
strcpy(skin->preskin->write_mode_name,"SAO");
goto check_with_drive;
}
was_still_default= 2; /* do not try more than once */
goto check_with_drive;
}
fprintf(stderr,"cdrskin: HINT : If you are certain that the drive will do, try option -force\n");
return(0);
}
}
#ifdef Cdrskin_libburn_has_get_multi_capS
ret = burn_disc_get_multi_caps(skin->grabbed_drive,skin->write_type,&caps,0);
if (ret>0)
allows_multi= caps->multi_session;
burn_disc_free_multi_caps(&caps);
#endif
if(skin->multi && !allows_multi) {
if(skin->prodvd_cli_compatible) {
skin->multi= 0;
if(skin->verbosity>=Cdrskin_verbose_progresS)
fprintf(stderr, "cdrskin: NOTE : Ignored option -multi.\n");
} else {
fprintf(stderr,
"cdrskin: SORRY : Cannot keep this media appendable after write by -multi\n");
return(0);
}
}
it_is_done:;
if(skin->write_type==BURN_WRITE_SAO && unpredicted_size==1)
for(i= 0; i<skin->track_counter; i++) {
Cdrtrack_get_size(skin->tracklist[i],&fixed_size,
&tao_to_sao_tsize,&dummy,2);
if(fixed_size<=0.0 && tao_to_sao_tsize>0.0) {
printf(
"cdrskin: NOTE : augmenting non-tao write mode by tao_to_sao_tsize\n");
printf("cdrskin: NOTE : fixed size : %.f\n",tao_to_sao_tsize);
Cdrtrack_activate_tao_tsize(skin->tracklist[i],0);
}
}
if(skin->verbosity>=Cdrskin_verbose_cmD)
printf("cdrskin: write type : %s\n", skin->preskin->write_mode_name);
return(1);
@ -4564,14 +4680,41 @@ int Cdrskin_burn(struct CdrskiN *skin, int flag)
printf("cdrskin: beginning to burn disk\n");
ret= Cdrskin_grab_drive(skin,0);
if(ret<=0)
goto burn_failed;
drive= skin->drives[skin->driveno].drive;
s= burn_disc_get_status(drive);
if(skin->verbosity>=Cdrskin_verbose_progresS)
Cdrskin_report_disc_status(skin,s,0);
#ifdef Cdrskin_allow_libburn_taO
if (s!=BURN_DISC_APPENDABLE && s!=BURN_DISC_BLANK) {
#else
if (s!=BURN_DISC_BLANK) {
#endif
Cdrskin_release_drive(skin,0);
fprintf(stderr,"cdrskin: FATAL : no writeable media detected.\n");
goto burn_failed;
}
ret= Cdrskin_activate_write_mode(skin,s,0);
if(ret<=0) {
fprintf(stderr,
"cdrskin: FATAL : Cannot activate the desired write mode\n");
goto burn_failed;
}
disc= burn_disc_create();
session= burn_session_create();
ret= burn_disc_add_session(disc,session,BURN_POS_END);
if(ret==0) {
fprintf(stderr,"cdrskin: FATAL : cannot add session to disc object.\n");
burn_failed:;
if(skin->verbosity>=Cdrskin_verbose_progresS)
printf("cdrskin: burning failed\n");
fprintf(stderr,"cdrskin: FATAL : burning failed.\n");
return(0);
}
skin->fixed_size= 0.0;
for(i=0;i<skin->track_counter;i++) {
hflag= (skin->verbosity>=Cdrskin_verbose_debuG);
@ -4580,59 +4723,24 @@ int Cdrskin_burn(struct CdrskiN *skin, int flag)
ret= Cdrtrack_add_to_session(skin->tracklist[i],i,session,hflag);
if(ret<=0) {
fprintf(stderr,"cdrskin: FATAL : cannot add track %d to session.\n",i+1);
return(0);
goto burn_failed;
}
Cdrtrack_get_size(skin->tracklist[i],&size,&padding,&sector_size,0);
if(size>0)
skin->fixed_size+= size+padding;
}
ret= Cdrskin_grab_drive(skin,0);
if(ret<=0)
return(ret);
drive= skin->drives[skin->driveno].drive;
#ifndef Cdrskin_no_aftergrab_loopS
while(burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
usleep(100002); /* >>> ??? add a timeout ? */
while((s= burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
usleep(100002); /* >>> ??? add a timeout ? */
#else
s= burn_disc_get_status(drive);
#endif
if(skin->verbosity>=Cdrskin_verbose_progresS)
Cdrskin_report_disc_status(skin,s,0);
ret= Cdrskin_activate_write_mode(skin,s,0);
if(ret<=0) {
fprintf(stderr,
"cdrskin: FATAL : Cannot activate the desired write mode\n");
ret= 0; goto ex;
}
#ifdef Cdrskin_libburn_has_multI
if (s == BURN_DISC_APPENDABLE) {
if (s==BURN_DISC_APPENDABLE) {
#ifdef Cdrskin_allow_sao_for_appendablE
;
#else
if(skin->write_type!=BURN_WRITE_TAO) {
Cdrskin_release_drive(skin,0);
fprintf(stderr,"cdrskin: FATAL : For now only write mode -tao can be used with appendable disks\n");
return(0);
goto burn_failed;
}
#endif /* ! Cdrskin_allow_sao_for_appendablE */
} else if (s != BURN_DISC_BLANK) {
#else
if (s != BURN_DISC_BLANK) {
#endif
Cdrskin_release_drive(skin,0);
fprintf(stderr,"cdrskin: FATAL : no writeable media detected.\n");
return(0);
}
#ifndef Cdrskin_extra_leaN
@ -4696,9 +4804,6 @@ int Cdrskin_burn(struct CdrskiN *skin, int flag)
burn_write_opts_set_perform_opc(o, 0);
#ifdef Cdrskin_libburn_has_multI
if(skin->multi)
fprintf(stderr,
"cdrskin: NOTE : Option -multi set. Media will be appendable.\n");
burn_write_opts_set_multi(o,skin->multi);
#endif
@ -4893,13 +4998,14 @@ fifo_full_at_end:;
if(wrote_well) {
if(skin->verbosity>=Cdrskin_verbose_progresS)
printf("cdrskin: burning done\n");
} else {
} else
ret= 0;
ex:;
if(ret<=0) {
if(skin->verbosity>=Cdrskin_verbose_progresS)
printf("cdrskin: burning failed\n");
fprintf(stderr,"cdrskin: FATAL : burning failed.\n");
ret= 0;
}
ex:;
skin->drive_is_busy= 0;
if(skin->verbosity>=Cdrskin_verbose_debuG)
ClN(printf("cdrskin_debug: do_eject= %d\n",skin->do_eject));
@ -5179,9 +5285,14 @@ set_blank:;
skin->do_blank= 1;
skin->blank_format_type= 1;
skin->blank_format_size= 0;
} else if(strcmp(cpt,"format_sequential")==0) {/* >>> not yet supported */
} else if(strcmp(cpt,"deformat_sequential")==0) {
skin->do_blank= 1;
skin->blank_format_type= 2;
skin->blank_fast= 0;
} else if(strcmp(cpt,"deformat_sequential_quickest")==0) {
skin->do_blank= 1;
skin->blank_format_type= 2;
skin->blank_fast= 1;
} else if(strcmp(cpt,"help")==0) {
/* is handled in Cdrpreskin_setup() */;
continue;
@ -5465,6 +5576,9 @@ set_padsize:;
if(skin->verbosity>=Cdrskin_verbose_cmD)
printf("cdrskin: padding : %.f\n",skin->padding);
} else if(strcmp(argv[i],"--prodvd_cli_compatible")==0) {
skin->prodvd_cli_compatible= 1;
} else if(strcmp(argv[i],"-raw96r")==0) {
/* is handled in Cdrpreskin_setup() */;
@ -5600,33 +5714,7 @@ track_too_large:;
}
}
}
if(! source_has_size) {
if(skin->fixed_size<=0.0) {
if(strcmp(skin->preskin->write_mode_name,"TAO")==0) {
/* with TAO it is ok to have an undefined track length */;
#ifdef Cdrskin_allow_libburn_taO
} else if(strcmp(skin->preskin->write_mode_name,"DEFAULT")==0) {
strcpy(skin->preskin->write_mode_name,"TAO");
#endif
} else if(skin->tao_to_sao_tsize>0.0) {
skin->fixed_size= skin->tao_to_sao_tsize;
printf(
"cdrskin: NOTE : augmenting non-tao write mode by tao_to_sao_tsize\n");
printf("cdrskin: NOTE : fixed size : %.f\n",skin->fixed_size);
} else {
fprintf(stderr,
#ifdef Cdrskin_allow_libburn_taO
"cdrskin: FATAL : Track source '%s' needs -tao or tsize= or tao_to_sao_tsize=\n",
#else
"cdrskin: FATAL : Track source '%s' needs a fixed tsize= or tao_to_sao_tsize=\n",
#endif
skin->source_path);
return(0);
}
}
}
if(skin->track_counter>=Cdrskin_track_maX) {
fprintf(stderr,"cdrskin: FATAL : too many tracks given. (max %d)\n",
Cdrskin_track_maX);

View File

@ -25,7 +25,7 @@
<P>
<H2>Purpose:</H2>
<UL>
<LI>Burns preformatted data to CD-R or CD-RW</LI>
<LI>Burns preformatted data to CD-R, CD-RW, DVD-R, DVD-RW, DVD-RAM, DVD+RW</LI>
</UL>
</P>
<P>
@ -34,9 +34,9 @@
<P>
<H2>Hardware requirements:</H2>
A CD recorder suitable for
A CD/DVD recorder suitable for
<A HREF="http://libburnia.pykix.org">libburnia.pykix.org</A>
(SCSI or IDE/ATAPI writers compliant to mmc-3 standard).
(SCSI or IDE/ATAPI writers compliant to standard MMC-3 or higher).
<BR>
</P>
@ -56,7 +56,7 @@ A CD recorder suitable for
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-0.2.6</DT>
<DT>libburn-0.3.2</DT>
<DD>(by Derek Foreman, Ben Jansens, and team of libburnia.pykix.org)</DD>
<DD>transfers data to CD</DD>
</DL>
@ -88,37 +88,74 @@ and for data CD projects of <A HREF="http://www.k3b.org">K3b</A>
(see <A HREF="#examples">examples</A>).
Suitability for audio CD frontends has been improved much and is now being
evaluated.<BR>
Most DVD types are written in pseudo -tao modes which are very different
from the write mode DAO used by cdrecord(-ProDVD). With DVD-R[W] cdrskin
can use this write mode, too.<BR>
Further enhancements depend on people who can describe and discuss their
wishes as well as on the development of libburn.</DT>
<BR><BR>
<DT>Get an overview of drives:</DT>
<DD>$ cdrskin -scanbus</DD>
<DD>$ cdrskin dev=ATA -scanbus</DD>
<DD>$ cdrskin --devices</DD>
<DT>Get an overview of drives and their addresses:</DT>
<DD>$<KBD>&nbsp;cdrskin -scanbus</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin dev=ATA -scanbus</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin --devices</KBD></DD>
<DT>Get info about a particular drive or loaded media:</DT>
<DD>$ cdrskin dev=0,1,0 -checkdrive</DD>
<DD>$ cdrskin dev=ATA:1,0,0 -atip</DD>
<DD>$ cdrskin dev=/dev/hdc -toc</DD>
<DT>Make used CD-RW writable again:</DT>
<DD>$ cdrskin -v dev=/dev/sg1 blank=all -eject</DD>
<DD>$ cdrskin -v dev=/dev/dvd blank=fast -eject</DD>
<DT>Write ISO-9660 filesystem image:</DT>
<DD>$ cdrskin -v dev=/dev/hdc speed=12 fs=8m driveropts=burnfree -sao -eject padsize=300k my_image.iso</DD>
<DT>Write compressed afio archive on-the-fly :</DT>
<DD>$ find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 driveropts=burnfree padsize=300k -tao -</DD>
<DT>Write audio tracks:</DT>
<DD>$ cdrskin -v dev=ATA:1,0,0 speed=48 driveropts=burnfree -sao track1.wav track2.au -audio -swab track3.raw
<DD>
<BR>
<DD>$<KBD>&nbsp;cdrskin dev=0,1,0 -checkdrive</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -toc</KBD></DD>
<DT>Make used CD-RW or used unformatted DVD-RW writable again:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sg1 blank=fast -eject</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/dvd blank=all -eject</KBD></DD>
<DT>Format DVD-RW to avoid need for blanking before re-use:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sr0 blank=format_overwrite</KBD></DD>
<DT>De-format DVD-RW to make it capable of multi-session again:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sr0 blank=deformat_sequential</KBD></DD>
<DT>Write ISO-9660 filesystem image as only one to blank or formatted media:
</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/hdc speed=12 fs=8m \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-sao -eject padsize=300k my_image.iso</KBD></DD>
<DT>Write compressed afio archive on-the-fly:</DT>
<DD>$<KBD>&nbsp;find . | afio -oZ - | \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;cdrskin -v dev=0,1,0 fs=32m speed=8 \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-tao padsize=300k -</KBD></DD>
<DT>Write several sessions to the same CD or DVD-R[W]:</DT>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -tao 4.iso</KBD></DD>
<DT>Get CD or DVD-R[W] multi-session info for option -C of program mkisofs:</DT>
<DD>$<KBD>&nbsp;c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)</KBD></DD>
<DD>$<KBD>&nbsp;mkisofs ... -C "$c_values" ...</KBD></DD>
<DT>Write audio tracks to CD:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=ATA:1,0,0 speed=48 -sao \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;track1.wav track2.au -audio -swab track3.raw</KBD></DD>
<DT>Get overview of the cdrecord compatible options:</DT>
<DD><A HREF="cdrskin_help">$ cdrskin -help</A></DD>
<DD>$<KBD>&nbsp;<A HREF="cdrskin_help">cdrskin -help</A></KBD></DD>
<DT>Get overview of the non-cdrecord options:</DT>
<DD><A HREF="cdrskin__help">$ cdrskin --help</A></DD>
<DD>$<KBD>&nbsp;<A HREF="cdrskin__help">cdrskin --help</A></KBD></DD>
<DT>Read the detailed manual page:</DT>
<DD><A HREF="man_1_cdrskin.html">$ man cdrskin</A></DD>
<DD>$<KBD>&nbsp;<A HREF="man_1_cdrskin.html">man cdrskin</A></KBD></DD>
</DL>
<DL>
<DT>Read about the standard for which cdrskin is striving:</DT>
<DD><A HREF="http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html">
$ man cdrecord</A></DD>
<DD>$<KBD>&nbsp;
<A HREF="http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html">
man cdrecord</A></KBD></DD>
<DD><B>Do not bother Joerg Schilling with any cdrskin problems.</B>
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
this "don't bother Joerg" demand.)
@ -153,10 +190,9 @@ rw-permissions and retry the bus scan as non-superuser.
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-0.2.6.pl02.tar.gz">cdrskin-0.2.6.pl02.tar.gz</A>
(510 KB).
<DD><A HREF="cdrskin-0.3.2.pl00.tar.gz">cdrskin-0.3.2.pl00.tar.gz</A>
(570 KB).
</DD>
<DD>(Most recent patch: backported man page from cdrskin-0.2.7)</DD>
<DD>
The "stable" cdrskin tarballs are source code identical with "stable"
libburn releases or with "stabilized" libburn SVN snapshots. They get
@ -165,14 +201,14 @@ cdrskin is part of libburn - full libburn is provided with cdrskin releases.
</DD>
<DD>&nbsp;</DD>
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
<DD><A HREF="cdrskin_0.2.6.pl01-x86-suse9_0.tar.gz">
cdrskin_0.2.6.pl01-x86-suse9_0.tar.gz</A>, (60 KB),
<DD><A HREF="cdrskin_0.3.2.pl00-x86-suse9_0.tar.gz">
cdrskin_0.3.2.pl00-x86-suse9_0.tar.gz</A>, (80 KB),
<DL>
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
Gentoo (2.6.15 x86_64 Athlon).</DD>
</DL>
<DD><A HREF="cdrskin_0.2.6.pl01-x86-suse9_0-static.tar.gz">
cdrskin_0.2.6.pl01-x86-suse9_0-static.tar.gz</A>, (260 KB), -static compiled,
<DD><A HREF="cdrskin_0.3.2.pl00-x86-suse9_0-static.tar.gz">
cdrskin_0.3.2.pl00-x86-suse9_0-static.tar.gz</A>, (285 KB), -static compiled,
<DL>
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
</DL>
@ -199,23 +235,14 @@ cdrskin_0.2.6.pl01-x86-suse9_0-static.tar.gz</A>, (260 KB), -static compiled,
<HR>
<P>
Enhancements towards previous stable version cdrskin-0.2.4:
Enhancements towards previous stable version cdrskin-0.3.0:
<UL>
<LI>Option <KBD><B>-tao</B></KBD> is fully enabled.<BR>
SAO is still the preferred default but TAO is default if a track of
unpredicted size is present (stdin, named pipe, ...) or if a follow-up
session is written to an appendable CD.
(This is an intentional deviation from cdrecord defaults which themselves
have changed with the newest cdrecord versions.)
</LI>
<LI>Status report during blank, preparation and finalization improved.</LI>
<LI>Bug fixed: Trailing trash appended to .wav files caused error message
and, if exceeding fifo size, could even stall a burn.
(Workaround: disable fifo by <KBD><B>fs=0</B></KBD>)</LI>
<LI>Bug fixed: False speed with first pacifier cycle. Potential program
abort by floating point exception (NaN).</LI>
<LI>multi-session CDs: <KBD><B>-multi</B></KBD>, <KBD><B>-msinfo</B></KBD>,
writing to appendable CDs (for now restricted to write mode TAO).</LI>
<LI>Burnfree enabled by default</LI>
<LI>Multi-session burning to DVD-R
and sequential (i.e. unformatted) DVD-RW</LI>
<LI>Option -toc with sequential DVD-R[W]</LI>
<LI>Options -msinfo and msifile= with appendable DVD-R[W]</LI>
<LI>Single session DAO write mode with DVD-R[W]</LI>
</UL>
</P>
@ -223,23 +250,17 @@ Enhancements towards previous stable version cdrskin-0.2.4:
<P>
<DL>
<DT><H3>Development snapshot, version 0.2.7 :</H3></DT>
<DD>Enhancements towards stable version 0.2.6:
<DT><H3>Development snapshot, version 0.3.3 :</H3></DT>
<DD>Enhancements towards stable version 0.3.2:
<UL>
<LI>Improved recognition of unsuitable media types</LI>
<LI>Ban of chmod u+s is replaced by a loud warning</LI>
<LI>Detailed man page (already backported to cdrskin-0.2.6.pl02)</LI>
<LI>Burning to DVD+RW and DVD-RAM as non-multi, non-appending,
single-track session</LI>
<LI>Formatting and then burning to DVD-RW like to DVD+RW</LI>
<LI>Emulation of new wodim option msifile=path</LI>
<LI>- none yet -</LI>
</UL>
</DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 0.2.7</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.2.7 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.2.7 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.2.7)</A></DD>
<DD><A HREF="README_cdrskin_devel">README 0.3.3</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.3.3 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.3.3 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.3.3)</A></DD>
<DD>&nbsp;</DD>
<DT>Maintainers of cdrskin unstable packages please use SVN of
<A HREF="http://libburnia.pykix.org"> libburnia.pykix.org</A></DT>
@ -259,15 +280,15 @@ admins with full system souvereignty.</DT>
<A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD>
<DD>
<A HREF="cdrskin-0.2.7.tar.gz">cdrskin-0.2.7.tar.gz</A>
(550 KB).
<A HREF="cdrskin-0.3.3.tar.gz">cdrskin-0.3.3.tar.gz</A>
(570 KB).
</DD>
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
<DD><A HREF="cdrskin_0.2.7-x86-suse9_0.tar.gz">
cdrskin_0.2.7-x86-suse9_0.tar.gz</A>, (75 KB).
<DD><A HREF="cdrskin_0.3.3-x86-suse9_0.tar.gz">
cdrskin_0.3.3-x86-suse9_0.tar.gz</A>, (80 KB).
</DD>
<DD><A HREF="cdrskin_0.2.7-x86-suse9_0-static.tar.gz">
cdrskin_0.2.7-x86-suse9_0-static.tar.gz</A>, (275 KB)
<DD><A HREF="cdrskin_0.3.3-x86-suse9_0-static.tar.gz">
cdrskin_0.3.3-x86-suse9_0-static.tar.gz</A>, (280 KB)
</DD>
</DL>
</P>
@ -283,6 +304,10 @@ Historic versions based on Derek's and Ben's
<A HREF="http://icculus.org/burn">icculus.org/burn</A> :<BR>
<A HREF="cdrskin-0.1.2.0.2.ts.tar.gz">cdrskin-0.1.2.0.2.ts.tar.gz</A><BR>
<A HREF="cdrskin-0.1.3.0.2.ts.tar.gz">cdrskin-0.1.3.0.2.ts.tar.gz</A>
<BR>
Very special thanks to Andy Polyakov whose
<A HREF="http://fy.chalmers.se/~appro/linux/DVD+RW/tools">dvd+rw-tools</A>
provide libburn with invaluable examples on how to deal with DVD media.
</P>
<HR>
@ -325,7 +350,7 @@ is a GUI frontend which uses cdrecord for CD burning.)
<DD><KBD>...</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_SCSI_ADR="ATA:1,0,0"</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v tao_to_sao_tsize=650m"</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v"</B></KBD></DD>
<DD>$ <KBD><B>scdbackup_home</B></KBD></DD>
</DL>
<DL>
@ -334,7 +359,7 @@ is a GUI frontend which uses cdrecord for CD burning.)
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>cdrskin 0.2.6 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
<DD><KBD>cdrskin 0.3.2 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
</DL>
If your system is stricken with some ill CD device then this can stall
and you will have to press <KBD>Ctrl+C</KBD> to abort.

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2007.01.14.133951"
#define Cdrskin_timestamP "2007.02.10.120001"

View File

@ -13,17 +13,23 @@ Deliberate deviations of cdrskin from cdrecord compatibility:
+ -sao is default where possible, -tao is default where needed
(Note: cdrecord write mode defaults have changed in cdrtools-2.01.01a20)
+ driveropts=burnfree is default if the drive supports buffer underrun
protection. If desired, use driveropts=noburnfree to disable this feature.
+ premature end of source is not an error and leads to full announced tracksize
+ -msinfo pushes all other messages to stderr. It works independent of
other options which would prevent it with cdrecord (-atip, -scanbus, ...)
+ DVD+RW writing is like -tao on giant blank CD-RW.
Same with DVD-RW in mode Restricted Overwrite.
+ DVD track sources get not concateneated to a single track. In general DVD
writing is quite different from cdrecord-ProDVD:
DVD-RW "Disc-at-once" (-sao) is nearest to cdrecord-ProDVD's methods.
DVD-RW "Incremental Streaming" (-tao) on unformatted media allows
multi-session and track sources of unpredictable size.
Writing DVD-RAM, DVD+RW and "Restricted Overwrite" DVD-RW is like single
track -tao on blank CD. Formatting is done via cdrskin-specific
blank=format_overwrite and not with option -format.
+ DVD-RW "Restricted Overwrite" writing is like DVD+RW (i.e. like -tao).
Formatting is done via cdrskin-specific blank=format_overwrite and not
with option -format.
------------------------------------------------------------------------------
Changelog
@ -1909,6 +1915,7 @@ Replaced setuid blocker by warning. People must know themselves what they do.
------------------------------------ cycle - cdrskin-0.2.7 - 2006.12.09.141837
* Replaced ban of chmod u+s by loud warning
11 Dec 2006 [484]
cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
@ -1995,6 +2002,7 @@ Took more care for man page
------------------------------------ cycle - cdrskin-0.2.7 - 2006.12.13.221921
* detailed man page for cdrskin
13 Dec 2006 [503]
cdrskin/changelog.txt
Next cdrskin-0.2.7 cycle
@ -2349,21 +2357,22 @@ Greeting the new year
------------------------------------ cycle - cdrskin-0.2.7 - 2007.01.02.101027
* Formatting and then burning to DVD-RW like to DVD+RW
2 Jan 2006 [576]
2 Jan 2007 [576]
cdrskin/changelog.txt
Next cdrskin-0.2.7 cycle
2 Jan 2006 [577]
2 Jan 2007 [577]
cdrskin/wiki_plain.txt
cdrskin/README
Some DVD-RW statements
2 Jan 2006 [578]
2 Jan 2007 [578]
test/libburner.c
doc/comments
Made use of formatting of DVD-RW
2 Jan 2006 [579]
2 Jan 2007 [579]
cdrskin/cdrskin.1
Some DVD-RW statements
@ -2442,54 +2451,590 @@ Updated size estimation of development downloads
cdrskin/changelog.txt
Next cdrskin-0.2.7 cycle
[]
2007.01.10.152350 [600]
libburn/libburn.h
libburn/mmc.c
libburn/drive.c
libburn/async.c
cdrskin/cdrskin.c
cdrskin/cdrskin.1
Option -force enables re-formatting
[]
2007.01.10.152520 [601]
libburn/mmc.c
Switched full formatting from type 10h to 00h which includes lead-out
[]
2007.01.10.152812 [602]
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
Removing writing of dummy data with blank=format_overwrite_full
Removed writing of dummy data with blank=format_overwrite_full
2007.01.10.204839 [603]
libburn/mmc.c
libburn/async.c
cdrskin/cdrskin.c
cdrskin/cdrskin.1
Enabled explicit full formatting of DVD+RW ("de-icing")
11 Jan 2007 [604]
cdrskin/README
Removed outdated option from startup file example
2007.01.11.131106 [605]
libburn/mmc.c
With full formatting prefer format 10h over 13h or 15h
2007.01.11.131302 [606]
libburn/os-linux.h
libburn/os-freebsd.h
libburn/cleanup.c
cdrskin/cleanup.c
Kept SIGWINCH from spoiling a burn.
2007.01.11.131615 [607]
libburn/init.c
Sketched better handling of self-inflicted SIGs
2007.01.11.131716 [608]
libburn/drive.c
Removed surplus newlines from messages
2007.01.12.162239 [609]
libburn/write.c
libburn/spc.c
libburn/mmc.c
cdrskin/cdrskin.c
cdrskin/cdrskin.1
Enabled writing to DVD-RAM
2007.01.13.140812 [610] [611]
libburn/sg-linux.c
Implemented debugging messages for ATA enumeration
13 Jan 2007 [612]
cdrskin/cdrskin_eng.html
cdrskin/README
Documentation updates about DVD-RAM
2007.01.13.211425 [613]
libburn/transport.h
libburn/mmc.c
Load array of format capacities into struct burn_drive
2007.01.13.211639 [614]
libburn/libburn.h
libburn/drive.c
libburn/async.c
Introduced API for inspection and selection of format capacities
13 Jan 2007 [615]
test/telltoc.c
Added printing of list of available formats
13 Jan 2007 [616]
test/libburner.c
Mentioned DVD-RAM where appropriate
2007.01.13.214259 [617]
cdrskin/cdrskin.c
Shifted fifo reporting to new 4-times -v verbosity level
2007.01.14.101742 [618]
cdrskin/cdrskin.c
Corrected bug with debug messages for fifo
2007.01.14.115347 [619]
libburn/write.c
Added missing cache sync in case of aborted DVD-RW burns
2007.01.14.133951 [620]
libburn/transport.h
libburn/mmc.c
libburn/write.c
Avoided closing of 0x13-DVD-RW sessions which are not intermediate
15 Jan 2007 [621]
cdrskin/wiki_plain.txt
Updated about overwriteable DVD and pointer to dvd+rw-tools
Format DVD+RW ?
------------------------------------ cycle - cdrskin-0.2.7 - 2007.01.15.131357
* Burning to DVD-RAM
Format and use DVD-RAM ?
Load format parameters into struct burn_drive and offer API.
With full formatting prefer format 10h over 13h or 15h.
15 Jan 2007 [623]
cdrskin/changelog.txt
Next cdrskin-0.2.7 cycle
Learn about multi-track with DVD-RW Restricted Overwrite.
2007.01.16.120001 [tag 624]
Makefile.am
configure.ac
README
cdrskin/cdrskin.c
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/changelog.txt
Made version number transition to 0.3.0
15 Jan 2007 [tag 625]
- cdrskin/add_ts_changes_to_libburn_0_2_6
- cdrskin/add_ts_changes_to_libburn_0_2_7
+ cdrskin/add_ts_changes_to_libburn_0_3_0
Updated cdrskin tarball generator
16 Jan 2007 [tag 626]
README
Corrected statement about restriction to CD
16 Jan 2007 [tag 627]
cdrskin/cdrskin.c
Silenced a compiler warning
16 Jan 2007 [tag 628]
cdrskin/README
Corrected name of tarball
16 Jan 2007 [tag 632]
test/telltoc.c
Corrected old libburn.pykix.org URL
16 Jan 2007 [tag 634]
cdrskin/cdrskin_eng.html
Updated web page
------------------------------- cycle - cdrskin-0.3.0.pl00 - 2007.01.16.120001
* Improved recognition of unsuitable media types
* Replaced ban of chmod u+s by loud warning
* detailed man page for cdrskin
* Burning of DVD+RW and DVD-RAM media as single-track TAO-like initial session
* Formatting and then burning to DVD-RW like to DVD+RW
* New option -msifile=path from cdrkit/wodim
16 Jan 2007 [629]
- cdrskin/add_ts_changes_to_libburn_0_2_6
- cdrskin/add_ts_changes_to_libburn_0_2_7
+ cdrskin/add_ts_changes_to_libburn_0_3_0
+ cdrskin/add_ts_changes_to_libburn_0_3_1
Updated cdrskin tarball generator
2007.01.16.151041 [630]
Makefile.am
configure.ac
cdrskin/cdrskin.c
cdrskin/README
cdrskin/compile_cdrskin.sh
Made version number transition to 0.3.1
16 Jan 2007 [631]
test/telltoc.c
Corrected old libburn.pykix.org URL
16 Jan 2007 [633]
cdrskin/cdrskin_eng.html
Corrected typo
------------------------------------ cycle - cdrskin-0.3.1 - 2007.01.16.152345
16 Jan 2007 [635]
cdrskin/changelog.txt
Next cdrskin-0.3.1 cycle
17 Jan 2007 [636]
cdrskin/wiki_plain.txt
Removed paragraph about obsoleted tao_to_sao_tsize=
18 Jan 2007 [637]
+ doc/cookbook.txt
Wrote down what i learned from implementing support for overwriteable DVD
18 Jan 2007 [638]
doc/cookbook.txt
More info about Current/Maximum Capacity Descriptor
18 Jan 2007 [639]
doc/cookbook.txt
Made clarification about formatting state recognition
2007.01.18.211740 [640]
libburn/transport.h
libburn/mmc.c
libburn/write.c
Kept DVD+RW from stopping BG formatting if it was not started at all
2007.01.19.110510 [641]
libburn/mmc.c
Removed forgotten debug message printed to stderr
19 Jan 2007 [642]
doc/cookbook.txt
Began to describe TAO multi-session CD writing
20 Jan 2007 [643]
doc/cookbook.txt
Changes with CD part. Especially explanation of TOC.
2007.01.21.190928 [644]
cdrskin/cdrskin.c
Removed unnecessary after-grab loops
2007.01.21.191058 [645]
libburn/write.c
Comments learned from studying MMC-3 and MMC-5 for SAO CD cookbook
21 Jan 2007 [646]
doc/cookbook.txt
Clarification about TAO and mode page 05h per track
2007.01.22.114245 [647]
libburn/libburn.h
libburn/write.c
libburn/async.c
libburn/libdax_msgs.h
cdrskin/cdrskin.c
Bug fix: Banned mixed mode SAO (because broken in libburn and unclear in MMC)
23 Jan 2007 [648]
doc/cookbook.txt
Added SAO CD Cookbook
23 Jan 2007 [649]
doc/cookbook.txt
Corrections of typos and text debris
2007.01.25.145846 [652]
libburn/structure.c
Bug fix: DVD tracks of defined size >=2GB suffered 32-bit integer wraparound
2007.01.25.185214 [655]
libburn/libburn.h
libburn/write.c
libburn/structure.h
libburn/structure.c
libburn/file.h
libburn/file.c
Enforce minimum track length with SAO
2007.01.25.180001 [tag 656]
libburn_0_3_0_1/libburn/structure.c
libburn_0_3_0_1/cdrskin/cdrskin_timestamp.h
libburn_0_3_0_1/cdrskin/README
Bug fix: DVD tracks of defined size >=2GB suffered 32-bit integer wraparound
26 Jan 2007 [tag 657]
libburn_0_3_0_1/cdrskin/cdrskin_eng.html
Mentioned new cdrskin patch level 01
26 Jan 2007 [658]
cdrskin/cdrskin_eng.html
Now offering cdrskin-0.3.0.pl01 for download
------------------------------------ cycle - cdrskin-0.3.1 - 2007.01.26.111920
2007.01.26.173236 [659]
libburn/file.h
libburn/file.c
Unified burn_file_source and burn_fd_source
27 Jan 2007 [660]
libburn/null.c
Initialized member set_size of burn_source within burn_null_source_new()
27 Jan 2007 [tag 661]
libburn_0_3_0_1/libburn/file.c
Removed 1.3 GB curbs for sources created by burn_file_source_new()
29 Jan 2007 [662]
doc/cookbook.txt
Added a statement about blanking of DVD-RW
2007.01.29.175822 [663]
libburn/transport.h
libburn/drive.c
libburn/write.c
libburn/mmc.c
Experiments about list of features and profiles
2007.01.30.165317 [664]
libburn/write.c
libburn/mmc.c
Preparations for DVD-R[W] Sequential Recording
2007.01.30.191740 [665]
libburn/write.c
libburn/mmc.c
First successful multi-session write to a sequential DVD-RW
30 Jan 2007 [666]
doc/cookbook.txt
Added snapshot of emerging sequential DVD-R[W] cookbook
2007.01.30.220220 [667]
cdrskin/cdrskin.c
cdrskin/cdrskin.1
Enabled Burnfree buffer underrun protection by default
2007.01.31.130100 [668]
libburn/async.c
cdrskin/cdrskin.c
cdrskin/cdrskin.1
Blank sequential DVD-RW, deformat overwriteable DVD-RW
2007.01.31.173611 [669]
libburn/libburn.h
libburn/transport.h
libburn/drive.c
libburn/mmc.c
cdrskin/cdrskin.c
cdrskin/cdrskin.1
Provisorily obtain multi-session -C parameters (violates MMC specs but works)
2007.02.01.161634 [670]
libburn/libburn.h
libburn/transport.h
libburn/mmc.c
test/telltoc.c
cdrskin/cdrskin.c
cdrskin/cdrskin.1
Obtain TOC from non-CD via 52h READ TRACK INFORMATION
2007.02.01.163511 [671]
cdrskin/cdrskin.c
Reacted on justified compiler warning about unitialized sessions variable
2007.02.01.191638 [672]
libburn/mmc.c
cdrskin/cdrskin.c
Allow blanking of DVD-RW which offer no Incremental Streaming
1 Feb 2007 [673]
cdrskin/cdrskin_eng.html
cdrskin/README
cdrskin/cdrskin.1
Prepared next cdrskin-0.3.1 cycle
1 Feb 2007 [674]
cdrskin/changelog.txt
Prepared next cdrskin-0.3.1 cycle
1 Feb 2007 [675] [676]
cdrskin/cdrskin.1
Mentioned DVD-RW multi-session in overview of features
------------------------------------ cycle - cdrskin-0.3.1 - 2007.02.01.203057
* Burnfree enabled by default
* Multi-session recording on sequential DVD-RW, including -toc, -msinfo
2 Feb 2007 [677]
cdrskin/convert_man_to_html.sh
Some sed expressions for beautification
2 Feb 2007 [678]
doc/cookbook.txt
Updated about DVD-R[W] blanking, multi-session info and TOC
2007.02.02.151327 [679]
libburn/mmc.c
test/telltoc.c
Make mmc_read_multi_session_c1 use TOC if available
2007.02.02.173345 [680]
libburn/mmc.c
cdrskin/cdrskin.c
Improved classification and TOC of finalized DVD-R[W] media
------------------------------------ cycle - cdrskin-0.3.1 - 2007.02.02.183755
3 Feb 2007 [681]
cdrskin/cdrskin.1
cdrskin/wiki_plain.txt
Mentioned DVD-RW multi-session
2007.02.03.205526 (comitted 4 Feb 2007) [682]
libburn/libburn.h
libburn/mmc.c
libburn/drive.c
libburn/async.c
test/telltoc.c
New in API : struct burn_multi_caps and burn_disc_get_multi_caps()
2007.02.05.132335 [683]
libburn/transport.h
libburn/mmc.c
Preparations for DVD-R[W] DAO
2007.02.06.130410 [684]
libburn/libburn.h
libburn/mmc.c
libburn/write.c
libburn/drive.c
libburn/libdax_msgs.h
Implemented DVD-R[W] DAO as BURN_WRITE_SAO
2007.02.06.170621 [685]
libburn/write.c
libburn/mmc.c
Beautification of debugging messages
2007.02.06.174320 [686]
cdrskin/cdrskin.c
tao_to_sao_tsize= for DVD-R[W] DAO
2007.02.06.185534 [687]
libburn/async.c
cdrskin/cdrskin.c
Enabled fast blank for DVD-R[W]
6 Feb 2007 [688]
cdrskin/cdrskin.1
Clarified CD and DVD peculiarities
6 Feb 2007 [689]
doc/cookbook.txt
Described DVD-R[W] DAO mode
------------------------------------ cycle - cdrskin-0.3.1 - 2007.02.06.200802
* DVD-R[W] Disk-at-once writing
6 Feb 2007 [690]
cdrskin/README
cdrskin/changelog.txt
cdrskin/cdrskin_eng.html
Next cdrskin-0.3.1 cycle
2007.02.07.162836 [691]
libburn/libburn.h
libburn/drive.h
libburn/drive.c
libburn/options.c
libburn/libdax_msgs.h
New API function burn_write_opts_auto_write_type()
7 Feb 2007 [692]
test/libburner.c
Made use of burn_write_opts_auto_write_type()
7 Feb 2007 [693]
test/libburner.c
doc/comments
Updated documentation aspects
8 Feb 2007 [694]
README
doc/comments
cdrskin/cdrskin.1
cdrskin/README
Finally made tests with DVD-R. They burn indeed like DVD-RW.
2007.02.08.210744 [695]
cdrskin/cdrskin.c
cdrskin/cdrskin.1
New option --prodvd_cli_compatible
8 Feb 2007 [696]
cdrskin/wiki_plain.txt
cdrskin/cdrskin_eng.html
Mentioned DVD-R
2007.02.08.225208 [697]
cdrskin/cdrskin.c
Silenced compiler warning
------------------------------------ cycle - cdrskin-0.3.1 - 2007.02.09.074058
9 Feb 2006 [698]
cdrskin/cdrskin_eng.html
Added special thanks towards Andy Polyakov
9 Feb 2006 [699]
cdrskin/cdrskin.1
doc/cookbook.txt
Small corrections in documentation
10 Feb 2007 [tag 701]
- cdrskin/add_ts_changes_to_libburn_0_3_0
- cdrskin/add_ts_changes_to_libburn_0_3_1
+ cdrskin/add_ts_changes_to_libburn_0_3_2
+ cdrskin/add_ts_changes_to_libburn_0_3_3
Updated cdrskin tarball generator
2007.02.10.120001 [tag 702]
Makefile.am
configure.ac
README
cdrskin/cdrskin.c
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/wiki_plain.txt
cdrskin/cdrskin_eng.html
Made number transition and activated development documentation
[]
cdrskin/changelog.txt
Documented changes and 0.3.2 release timestamp
------------------------------- cycle - cdrskin-0.3.2.pl00 - 2007.02.10.120001
* Burnfree enabled by default
* Multi-session recording on sequential DVD-R[W], including -toc, -msinfo
* DVD-R[W] Disk-at-once recording
Bug reports to post after release:
See A70205_to_cdwrite_growisofs_dao_pitfalls
A70208_to_cdwrite_cdrecord_error_messages
A70209_to_cdrskit_error_messages
------------------------------------ cycle - cdrskin-0.3.3 -
forceful blanking of blank media in burn_disc_erase()
What about minimum track sizes ? (POWER OFF/ON , BUS RESET ?)
growisofs does not finalize multi-session DVD[+-]R unless padding up. Why ?
cdrskin: prevent usage of burn drive as track source
move tao_to_sao_tsize into libburn and let cdrskin use auto write mode
Make wide use of mmc_four_char_to_int(), mmc_int_to_four_char()
Make wide use of burn_disc_write_mode_demands()
Remove from README what is also written in the man page.
Think about cdrecord option minbuf= for simultaneous operation on hdc and hdd
After cooking: review of -do_diet ?
growisofs.c : _LINUX_CAPABILITY_VERSION CAP_SYS_RAWIO SYS_capset ?
Format DVD-RAM ?
How to handle finalizing ?
Check wether current_profile is kept up to date with each possible media change
Make drive_info reflect DVD capabilities
Make proper use of reflected capabilities (e.g. in burn_drive_inquire_media())
Rectify mmc_read_atip speed interpretation. 12x media are reported as 10x. I never heard of 6x media.
Sequentially check option list for DVD compliance
------------------------------------ cycle - cdrskin-0.2.7 -
----------------------------------------- long term intentions:
http://burbon04.gmxhome.de/linux/CDREncryption.html
[]
Ticket 90: failure on USB

View File

@ -7,7 +7,7 @@
debug_opts=
def_opts=
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
libvers="-DCdrskin_libburn_0_2_7"
libvers="-DCdrskin_libburn_0_3_2"
cleanup_src_or_obj="libburn/cleanup.o"
libdax_msgs_o="libburn/libdax_msgs.o"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
@ -33,15 +33,15 @@ do
libdax_audioxtr_o=
libdax_msgs_o="libburn/message.o"
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_2_6"
elif test "$i" = "-libburn_0_3_2"
then
libvers="-DCdrskin_libburn_0_2_6"
libvers="-DCdrskin_libburn_0_3_2"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
elif test "$i" = "-libburn_svn"
then
libvers="-DCdrskin_libburn_0_2_7"
libvers="-DCdrskin_libburn_0_3_3"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
@ -79,7 +79,7 @@ do
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
echo " -compile_dewav compile program test/dewav without libburn."
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
echo " -libburn_0_2_6 set macro to match libburn-0.2.6."
echo " -libburn_0_3_2 set macro to match libburn-0.3.2."
echo " -libburn_svn set macro to match current libburn-SVN."
echo " -no_largefile do not use 64 bit off_t (must match libburn)."
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."

View File

@ -47,7 +47,8 @@ then
-e 's/In general there are two types of tracks: data and audio./\&nbsp;<BR>In general there are two types of tracks: data and audio./' \
-e 's/While audio tracks just contain a given/\&nbsp;<BR>While audio tracks just contain a given/' \
-e 's/<b>Recordable CD Media:<\/b>/\&nbsp;<BR><b>Recordable CD Media:<\/b>/' \
-e 's/<b>Recordable DVD Media:<\/b>/\&nbsp;<BR><b>Recordable DVD Media:<\/b>/' \
-e 's/<b>Overwriteable DVD Media:<\/b>/\&nbsp;<BR><b>Overwriteable DVD Media:<\/b>/' \
-e 's/<b>Sequentially Recordable DVD Media:<\/b>/\&nbsp;<BR><b>Sequentially Recordable DVD Media:<\/b>/' \
-e 's/<b>Drive preparation and addressing:<\/b>/\&nbsp;<BR><b>Drive preparation and addressing:<\/b>/' \
-e 's/If you only got one CD capable drive/\&nbsp;<BR>If you only got one CD capable drive/' \
-e 's/^Alphabetical list of options/\&nbsp;<BR>Alphabetical list of options/' \

View File

@ -7,8 +7,11 @@
Its paragon, cdrecord, is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for the services
traditionally provided by cdrecord. Currently it does CD-R and CD-RW.
Its future ability to burn DVD media depends on the development of libburn.
traditionally provided by cdrecord. Currently it does CD-R and CD-RW this way.
Overwriteable media DVD-RAM, DVD+RW and DVD-RW are handled differently than
with cdrecord-ProDVD in order to offer TAO-like single track recording.
Sequential DVD-R[W] are handled like CD-R[W] with TAO and multi-session.
Additionally cdrskin offers cdrecord-ProDVD-like mode DAO with DVD-R[W].
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord
@ -19,14 +22,13 @@ About libburn API for burning CD: http://libburnia-api.pykix.org
--------------------------------------------------------------------------
Appending sessions to an unclosed CD is restricted to write mode TAO.
(Users who have a burner which succeeds with a follow-up session via
Appending sessions to an unclosed CD or DVD-R[W] is restricted to write mode
TAO. (Users who have a burner which succeeds with a follow-up session on CD via
cdrecord -sao : please contact us.)
The development version of cdrskin is able to burn a single track to DVD+RW
or DVD-RW media.
For other DVD types and for appending sessions to ISO filesystems see the
advise to use dvd+rw-tools at the end of this text.
For DVD types other than DVD-RAM, DVD+RW, DVD-RW, DVD-R and for appending
sessions to ISO filesystems on DVD other than DVD-RW, DVD-R see the advise
to use dvd+rw-tools at the end of this text.
--------------------------------------------------------------------------
@ -83,20 +85,42 @@ has to offer both, r- and w-permission.
--------------------------------------------------------------------------
Non-cdrecord blank mode blank=format_overwrite is needed to bring a DVD-RW
The DVD capabilities of cdrskin differ from those of cdrecord-ProDVD. cdrskin
lacks of support for DVD+R and for dual layer DVD media. On the other hand it
offers TAO-like multi-session with DVD-R[W] and TAO-like single session with
overwriteable DVD media. It also offers DAO on DVD-R[W] which is probably the
same as the traditional cdrecord-ProDVD write mode.
Non-cdrecord blank mode blank=format_overwrite brings a DVD-RW
disc from its initial profile "Sequential Recording" into profile state
"Restricted Overwrite". The latter is usable with cdrskin.
"Restricted Overwrite".
{{{
cdrskin dev=/dev/sr0 -v blank=format_overwrite
}}}
DVD-RW "Restricted Overwrite" and DVD+RW appear to cdrskin as blank media
DVD-RAM, DVD+RW and overwriteable DVD-RW appear to cdrskin as blank media
which are capable of taking only a single track. This track may be positioned
on a 32KiB aligned address, though.
{{{
cdrskin ... write_start_address=2412m ...
}}}
Non-cdrecord blank mode blank=deformat_sequential brings an overwriteable
DVD-RW back into state "Sequential Recording" with the capability of doing
multi-session, if the drive is capable of "Incremental Streaming"
(MMC feature 21h).
Used sequential DVD-RW media may be blanked by blank=fast or blank=all which
normally both do full blanking.
blank=deformat_sequential does minimal blanking of DVD-RW which usually yields
media incapable of "Incremental Streaming".
Option --prodvd_cli_compatible activates blank=fast and blank=all for
overwriteable DVD-RW which normally ignore those two options. It also makes
option -multi tolerable with media and write modes which are not suitable for
multi-session. (The default behavior of cdrskin deems me to be preferrable.)
--------------------------------------------------------------------------
fifo_start_at=<num> is a throughput enhancer for unsteady data streams
@ -154,21 +178,6 @@ $HOME/.cdrskinrc
--------------------------------------------------------------------------
tao_to_sao_tsize=<num> allows the - actually unsupported - cdrecord option
-tao and defines a default track size to be used if - as custom with -tao -
no option tsize=# is given.
Since -tao is supported in cdrskin-0.2.6 the TAO-to-SAO workaround has become
quite obsolete. Nevertheless, tao_to_sao_tsize= allows to preset a default
size for SAO mode which is in effect only if no track size is available.
As in general with cdrskin tsize=# the data source does not have to provide
the full annouced amount of data. Missing data will be padded up by 0-bytes.
Surplus data is supposed to cause an error, though. The burn will then
be a failure in any way.
--------------------------------------------------------------------------
dev_translation=<sep><from><sep><to> may be needed to foist cdrskin to
frontend programs of cdrecord which do *not* ask cdrecord -scanbus but
which make own assumptions and guesses about cdrecord's device addresses.
@ -200,9 +209,10 @@ for an illustrated example with K3b 0.10 .
DVD advise:
For burning of DVD media the cdrskin project currently advises to use
Andy Polyakov's dvd+rw-tools which despite their historic name burn
for me on above burner: DVD+RW, DVD+R, DVD-RW, DVD-R .
For burning of DVD media other than DVD-RAM, DVD+RW, DVD-RW, DVD-R, the cdrskin
project currently advises to use Andy Polyakov's dvd+rw-tools which despite
their historic name burn for me on above burner: DVD-RAM, DVD+RW, DVD+R,
DVD-RW, DVD-R and are also capable of dual layer and even BD discs.
http://fy.chalmers.se/~appro/linux/DVD+RW/tools
@ -210,21 +220,18 @@ They are not compatible or related to cdrecord resp. cdrecord-ProDVD
(now obsoleted by original source cdrtools cdrecord with identical
capabilities besides the license key).
libburn and thus the cdrskin project are currently aquiring own capabilities
to burn to DVD media. For now restricted to DVD+RW and DVD-RW and to single
A special feature of dvd+rw-tools is growing of ISO-9660 filesystems on
overwriteable media. This is not the same as multi-session writing of cdrskin
with CD media, but retrieves additional information from the existing ISO
image and finally manipulates the start sectors of this existing image.
So for growable ISO filesystems on DVD-RAM or DVD+RW growisofs is the only
choice, currently.
cdrskin can offer DVD multi-session only with sequential DVD-R[W]. Associated
options blank=, -multi, -msinfo and -toc are available in this case. Thus
sequential DVD-RW behave much like large CD-RW with possibly more than 99
tracks.
To my knowledge, Linux kernels 2.6 do write to DVD+RW via block devices as
they would write to a traditional tape device. Try old tape archiver
commands with addresses like /dev/sr0 or /dev/hdc rather than /dev/mt0 .
I have heard rumors that DVD-RW in mode "restricted overwrite" would be
block device ready, too. My burner is not a real friend of DVD-RW and
in an experiment the burn worked fine - but the result was not identical
to the stream sent to the device. I had similar failure with DVD-RAM, too.
Beware of the impact of a slow block device on overall system i/o buffering.
It is wise to curb its input to a speed which it is able to deliver to media.
Else your i/o dedicated RAM might buffer a big amount of stream data.
--------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
AC_INIT([libburn], [0.2.7], [http://libburnia.pykix.org])
AC_INIT([libburn], [0.3.2], [http://libburnia.pykix.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
@ -7,12 +7,6 @@ AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([subdir-objects])
dnl A61101 This breaks Linux build (makes 32 bit off_t)
dnl http://sourceware.org/autobook/autobook/autobook_96.html says
dnl one must include some config.h and this was a pitfall.
dnl So why dig the pit at all ?
dnl AM_CONFIG_HEADER(config.h)
dnl Making releases:
dnl BURN_MICRO_VERSION += 1;
dnl BURN_INTERFACE_AGE += 1;
@ -24,8 +18,8 @@ dnl
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
dnl
BURN_MAJOR_VERSION=0
BURN_MINOR_VERSION=2
BURN_MICRO_VERSION=7
BURN_MINOR_VERSION=3
BURN_MICRO_VERSION=2
BURN_INTERFACE_AGE=0
BURN_BINARY_AGE=0
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
@ -76,12 +70,6 @@ AC_PROG_INSTALL
AC_CHECK_HEADERS()
AC_CHECK_MEMBER([struct tm.tm_gmtoff],
[AC_DEFINE(HAVE_TM_GMTOFF, 1,
[Define this if tm structure includes a tm_gmtoff entry.])],
,
[#include <time.h>])
THREAD_LIBS=-lpthread
AC_SUBST(THREAD_LIBS)

View File

@ -6,9 +6,9 @@
@section intro Introduction
Libburnia is an open-source project for reading, mastering and writing
optical discs. For now this means only CD-R and CD-RW.
Support for DVD+RW and DVD-RW is emerging.
optical discs. For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD-RW, DVD-R.
Not supported yet are DVD+R, any dual layer media, HD-DVD, BD (blue ray).
The project comprises of several more or less interdependent parts which
together strive to be a usable foundation for application development.
@ -20,9 +20,9 @@ we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
We have a workable code base for burning data and audio CDs. The burn API is
quite comprehensively documented and can be used to build a presentable
application.
We have a workable code base for burning data and audio CDs and many DVD types.
The burn API is quite comprehensively documented and can be used to build a
presentable application.
We have a functional binary which emulates the core use cases of cdrecord in
order to prove that usability, and in order to allow you to explore libburn's
scope by help of existing cdrecord frontends.
@ -32,7 +32,10 @@ scope by help of existing cdrecord frontends.
- libburn is the library by which preformatted data get onto optical media.
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
/dev/hdX (e.g. on kernel 2.6).
libburn is the foundation of our cdrecord emulation.
libburn is the foundation of our cdrecord emulation. Its code is
independent of cdrecord. Its DVD capabilities are learned from
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
the pure SCSI knowledge has been taken from dvd+rw-tools, though.
- libisofs is the library to pack up hard disk files and directories into a
ISO 9660 disk image. This may then be brought to CD via libburn.
@ -41,15 +44,18 @@ scope by help of existing cdrecord frontends.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
cdrecord is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for
the services traditionally provided by cdrecord.
the services traditionally provided by cdrecord. Additionally it
provides libburn's DVD capabilities, where only -sao is compatible
with cdrecord.
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord
runs, though.
See cdrskin/README for more.
- "test" is a collection of application gestures and examples given by the
authors of the library features. The main API example of libburn
is named test/libburner.c .
authors of the library features. The burn API example of libburn
is named test/libburner.c . The API for media information inquiry is
demonstrated in test/telltoc.c .
Explore these examples if you look for inspiration.
We plan to be a responsive upstream. Bear with us.
@ -82,9 +88,8 @@ languages and development tools.
libburner is a minimal demo application for the library libburn
(see: libburn/libburn.h) as provided on http://libburn.pykix.org .
It can list the available devices, can blank a CD-RW and
can burn to CD-R or CD-RW.
New: burning to DVD+/-RW (single data track, single session only).
It can list the available devices, can blank a CD-RW or DVD-RW and
can burn to CD-R, CD-RW, DVD-RAM, DVD+RW, DVD-RW, DVD-R.
It's main purpose, nevertheless, is to show you how to use libburn and also
to serve the libburnia team as reference application. libburner does indeed
@ -95,8 +100,9 @@ stay upward compatible for a good while.
<pre>
Usage: test/libburner
[--drive <address>|<driveno>|"-"] [--audio]
[--blank_fast|--blank_full] [--try_to_simulate]
[--multi] [one or more imagefiles|"-"]
[--blank_fast|--blank_full|--format_overwrite]
[--try_to_simulate]
[--multi] [<one or more imagefiles>|"-"]
Examples
A bus scan (needs rw-permissions to see a drive):
test/libburner --drive -
@ -106,22 +112,27 @@ Burn a file to drive chosen by persistent address, close:
test/libburner --drive /dev/hdc my_image_file
Blank a used CD-RW (is combinable with burning in one run):
test/libburner --drive /dev/hdc --blank_fast
Burn two audio tracks
Blank a used DVD-RW (is combinable with burning in one run):
test/libburner --drive /dev/hdc --blank_full
Format a DVD-RW to avoid need for blanking before re-use:
test/libburner --drive /dev/hdc --format_overwrite
Burn two audio tracks (to CD only):
lame --decode -t /path/to/track1.mp3 track1.cd
test/dewav /path/to/track2.wav -o track2.cd
test/libburner --drive /dev/hdc --audio track1.cd track2.cd
Burn a compressed afio archive on-the-fly:
( cd my_directory ; find . -print | afio -oZ - ) | \
test/libburner --drive /dev/hdc -
To be read from *not mounted* CD via: afio -tvZ /dev/hdc
Program tar would need a clean EOF which our padded CD cannot deliver.
To be read from *not mounted* media via: afio -tvZ /dev/hdc
</pre>
libburner has two companions, telltoc and dewav, which help to perform some
peripheral tasks of burning.
telltoc prints a table of content (sessions, tracks and leadouts), it tells
about type and state of CD media, and also is able to provide the necessary
multi-session information for program mkisofs option -C.
about type and state of media, and also is able to provide the necessary
multi-session information for program mkisofs option -C. Especially helpful
are its predictions with "Write multi" and "Write modes" where availability
of "TAO" indicates that tracks of unpredicted length can be written.
See: test/telltoc --help.
dewav extracts raw byte-swapped audio data from files of format .wav (MS WAVE)

966
doc/cookbook.txt Normal file
View File

@ -0,0 +1,966 @@
libburnia.pykix.org Optical Media Rotisserie Recipes as of February 2007
Content:
- TAO Multi-Session CD Cookbook (CD-R, CD-RW)
- SAO CD Cookbook (CD-R, CD-RW, pure audio or pure data only)
- Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW)
- Sequential DVD-R[W] Cookbook
-------------------------------------------------------------------------------
TAO Multi-Session CD Cookbook
-------------------------------------------------------------------------------
Guided by reading mmc-r10a.pdf , O.8 "Write a Track"
from http://www.t10.org/ftp/t10/drafts/mmc/
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
by reading spc3r23.pdf from http://www.t10.org/ftp/t10/drafts/spc3/
by reading libburn/* from http://icculus.org/burn
and by experiments with drives NEC ND-4570A, LG GSA-4082B, LITE-ON LTR48125S
which used in part code from http://icculus.org/burn.
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
Media type can be recognized by Current Profile from 46h GET CONFIGURATION.
(mmc5r03c.pdf 6.6.2.1)
CD-R 0009h
CD-RW 000ah
The following topics are covered in this text:
- About blank, appendable and finalized CD media
- Writing a session to CD in TAO mode
- Obtaining CD multi-session info for extending ISO-9660 filesystems
- Obtaining a Table Of Content from CD
-------------------------------------------------------------------------------
About blank, appendable and finalized CD media :
CD media have to be blank or appendable in order to be writeable in TAO mode.
The according status may be inquired by 51h READ DISC INFORMATION requesting
Data Type 000b Standard Disc Information, where reply value Disc Status
indicates:
00b blank
01b appendable
10b finalized
11b others (unsuitable for this recipe)
(mmc5r03c.pdf 6.22.3.1.4)
CD-RW which are finalized or appendable may be blanked by command A1h BLANK
with blanking types 000b "Blank the disc" or 001b "Minimally blank the disc".
The Start Address/Track Number will be ignored so it may well be 0.
Because the operation is long running it is advised to set the Immed bit and to
watch the progress by commands 00h TEST UNIT READY and 03h REQUEST SENSE
with DESC bit set to 0 for fixed format reply.
It is done when 00h succeeds and 03h reports 0 in PROGRESS INDICATION
(byte 1+2 in Table 22 = byte 16+17 SENSE KEY SPECIFIC in table 26).
(mmc5r03c.pdf 6.2 BLANK)
(spc3r23.pdf 4.5.2.4.4 table 22, 4.5.3 table 26,
6.27 REQUEST SENSE, 6.33 TEST UNIT READY)
-------------------------------------------------------------------------------
Writing a session to CD in TAO mode :
The writing method for blank or appendable media is the same. A new session
will get created automatically by the first track when it is written. If the
media is blank then the new session will be the first and only one in the
table of content. If the media is appendable then a new session will be
appended to the existing sessions. In any case the new track will be the
first one in the new session.
Speed may be set by BBh SET CD SPEED parameter Drive Write Speed. Note that
kbytes/sec means 1000 bytes/sec and not 1024/sec. Rotational control should
be set to 00b. 1x CD speed is 176.4 kbytes/sec. Speed is usually set to the
next lower possible value by the drive. So it is helpful to add a few
kbytes/sec just in case the drive has rounding problems.
(mmc5r03c.pdf 6.37)
Before writing can occur, a Write Parameters mode page 05h has to be composed
and transmitted via 55h MODE SELECT. Mode page 05h describes several burn
parameters:
BUFE Buffer Underrun protection 0=off, 1=on
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 01h = TAO
Multi-session Wether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 4 for data , 0 for audio
Data Block Type Layout of payload blocks 8 for 2048 byte data blocks
0 for 2352 byte audio blocks
Audio Pause Length 150 = 2 seconds
Any other parameters may be set to 0.
Mode page data as of MMC-5 table 644 are preceded by a Mode Parameter Header
as of SPC-3 table 240. This 8-byte header may be filled with zeros.
(mmc5r03c.pdf 7.5.4 The Mode Page, 4.2.3.4 Table 17 CONTROL = Track Mode)
(spc3r23.pdf 6.8 MODE SELECT, 7.4.3 Mode parameter header formats)
Writing has to begin at the address returned by 52h READ TRACK INFORMATION
with Address/Number Type set to 01b and Logical Block Address/Track/Session
Number set to FFh. The Next Writeable Address as of table 500 is the number
to start writing with.
(mmc5r03c.pdf 6.27 )
Writing is performed by one or more 2Ah WRITE transactions with the Logical
Block Address counted up from the initial number in sync with the number of
blocks written. I.e the Transfer Length of the previous 2Ah WRITE has to be
added to the Logical Block Address for the next 2Ah WRITE. Only full blocks
can be written.
(mmc5r03c.pdf, 6.44)
When writing is done, it is mandatory to force the drive's buffer to media by
35h SYNCHRONIZE CACHE.
(mmc5r03c.pdf, 6.41)
A track must at least contain 300 payload blocks: 4 seconds of audio or
600 KiB of data.
(mmc5r03c.pdf 6.3.3.1.2)
The track has to be closed by 5Bh CLOSE TRACK SESSION Close Function 001b.
Older MMC specifies a valid Logical Track Number FFh to depict the open track.
MMC-5 is quite silent about this. FFh works for my drives.
(mmc5r03c.pdf 6.3.3.1.2)
After that, a new track may be written beginning with sending the mode page 05h
again. It is not tested wether 05h can be omitted if Track Mode and Data Block
Type are the same as with the previous track.
The new track will be added to the session which was opened by the first track.
After the last track of a session, 5Bh CLOSE TRACK SESSION Close Function 010b
with Logical Track Number 0 closes the session. It depends on the Multi-Session
value in mode page 05h wether the disc is finalized or stays appendable.
(mmc5r03c.pdf 6.3.3.1.3)
-------------------------------------------------------------------------------
Obtaining CD multi-session info for extending ISO-9660 filesystems :
Program mkisofs expects two numbers with its option -C which describe the
situation on an appendable CD which already contains a ISO-9660 filesystem
in the first track of the last session.
The first number is the Logical Block Address of that track containing the
existing ISO-9660 filesystem image. This number is needed for mkisofs option
-M to connect to the existing image. The new image will refer to files in
the previously existing image. mkisofs option -M needs read access to the
CD or a blockwise copy of it on hard disk.
The number is gained by 43h READ TOC/PMA/ATIP.
(mmc5r03c.pdf 6.26)
Untested is Format 0001b which in table 478 promises quick access via
Start Address Of First Track In Last Session.
(mmc5r03c.pdf 6.26.2.5 table 478, 6.26.3.3.1)
libburn gets the number from its Table Of Content model which is obtained
by 43h READ TOC/PMA/ATIP, Format 0010b. See below.
The second number is an exact prediction of the Logical Block Address of the
new track which will contain the newly generated ISO-9660 image.
Even without mkisofs option -M this second number is still needed to make the
inner block address pointers of the image match the Logical Block Addresses
on CD. For that one may inquire 52h READ TRACK INFORMATION with
Address/Number Type set to 01b and Logical Block Address/Track/Session
Number set to FFh. The Next Writeable Address as of table 500 is the number
to use.
(mmc5r03c.pdf 6.27 )
-------------------------------------------------------------------------------
Obtaining a Table Of Content from CD :
The structure of a CD is comprised of sessions. Each session contains one or
more tracks and is followed by a lead-out. A track has an address and a length.
Table of content information is gained by 43h READ TOC/PMA/ATIP, Format 0010b.
(mmc5r03c.pdf 6.26.2.5 table 478)
The number of sessions is given by Last Complete Session Number.
The number of TOC Track descriptors is: (TOC Data Length - 2)/11 .
Each TOC Track Descriptor contains a Session Number.
If POINT is >= 1 and <= 99 (63h) then the descriptor is about the track of
which POINT tells the number.
The start address of this track can be read from PMIN, PSEC, PFRAME where
it is encoded in MSF format:
blocks = frames - 150, 75 frames = 1 sec , 60 sec = 1 min.
The length of the track is given by MIN,SEC,FRAME in the same format.
If POINT = A0h then the descriptor tells in PMIN the first track number of its
session.
POINT = A1h tells in PMIN the last track number of its session.
POINT = A2h describes in PMIN, PSEC, PFRAME the lead-out of a session, i.e the
first address after the session's end. (Next writeable address typically is
lead-out + 11400 after the first session, lead-out + 6900 after further
sessions.)
POINT = B0h tells in MIN,SEC,FRAME this next writeable address or FFh,FFh,FFh
for finalized disc.
(mmc5r03c.pdf 6.26.3.4 table 489, 4.2.3.7 Mode-1 Q, Mode-5 Q)
In libburn the address of the first track in the last session is obtained from
the last session's POINT = A0h and from the track descriptor with the POINT
value matching the PMIN value of the A0h descriptor.
Untested is wether POINT = B0h and 52h READ TRACK INFORMATION are always in
sync. libburn uses the info provided by 52h READ TRACK INFORMATION.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
SAO CD Cookbook
-------------------------------------------------------------------------------
Guided by reading libburn/* from http://icculus.org/burn
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
and by experiments with drives NEC ND-4570A, LG GSA-4082B, LITE-ON LTR48125S
which used in part code from http://icculus.org/burn.
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
Recognition of media type and state (blank, appendable, finalized) is as
described in the TAO Multi-Session CD Cookbook. See there.
The MMC specs do not give much hint about the combination of SAO and
multi-session. My drives refused not only on a few experiments which i did
in libburn but also failed with cdrecord -sao on an appendable CD.
So for now only blank CD seem to be suitable for SAO writing.
Different from TAO mode, the whole session layout is announced to the drive by
sending a Cue Sheet. This implies that the sizes of the tracks have to be known
in advance, which is a heavy drawback when dealing with track data sources like
stdin, named pipes or sockets.
Nevertheless, SAO seems to be best writing mode for audio purposes, as our
audio expert Lorenzo Taylor found out.
A SAO session in libburn may either consist entirely of audio tracks or
entirely of data tracks. For mixed sessions, only TAO is usable yet.
- Composing a SAO CD Cue Sheet (either audio or data, but not mixed)
- Writing the prepared SAO CD session
- What is known about mixed mode sessions
-------------------------------------------------------------------------------
Composing a Cue Sheet (either audio or data, but not mixed) :
The Cue Sheet will get submitted to the drive by 5Dh SEND CUE SHEET.
Each entry of the sheet is of 8 bytes size. Its fields are named
CTL|ADR, TNO, INDEX, DATA FORM, SCMS, MIN, SEC, FRAME .
(mmc5r03c.pdf 6.33)
CTL is 40h for data and 00h for audio.
(mmc5r03c.pdf 6.33.3.4)
ADR is always 01h.
TNO is the track number (1 to 99).
INDEX is a subaddress within tracks. This recipe uses only INDEX 01h within
tracks.
(mmc5r03c.pdf 4.2.3.5.2)
DATA FORM is 00h for audio payload , 10h for data. (01h for audio pause is not
used in libburn).
(mmc5r03c.pdf 6.33.3.11 CD-DA Data Form, 6.33.3.12 CD-ROM mode 1 Form)
SCMS is always 00h.
MIN, SEC, FRAME give the MSF address where the described data entity starts.
LBA = frames - 150, 75 frames = 1 sec , 60 sec = 1 min.
This address must increase from entry to entry (or at least stay equal).
The first entry describes the Lead-in. Its content is
(CTL|ADR ,00h,00h,01h,00h,00h,00h,00h)
With the CTL|ADR for the first track: 41h for data, 01h for audio.
The LBA for the first write is negative: -150. This corresponds to MSF address
00h:00h:00h. All addresses are to be given in MSF format.
The first information track on disc is preceded by a pause encoding of 2 sec:
(CTL|ADR,01h,00h, DATA FORM ,00h,00h,00h,00h)
with DATA FORM = 00h for audio and 10h for data. By those 2 seconds the MSF
address increases to 00h:02h:00h = LBA 0.
Each track is represented by an entry
(CTL|ADR, TNO ,01h,DATA FORM,00h, MIN , SEC , FRAME)
TNO gives the track number. MIN, SEC, FRAME give the MSF address which becomes
the start address of the track. The MSF address is then increased by the size
of the track (to be used with next track or with lead-out).
A track must at least contain 300 payload blocks: 4 seconds of audio or
600 KiB of data.
(mmc5r03c.pdf 6.33.3.6)
At the end of the session there is a lead-out entry
(CTL|ADR,AAh,01h,01h,00h,MIN,SEC,FRAME)
marking the end of the last track. (With libburn CTL is as of the last track.)
-------------------------------------------------------------------------------
Writing the prepared session :
Speed may be set by BBh SET CD SPEED parameter Drive Write Speed. Note that
kbytes/sec means 1000 bytes/sec and not 1024/sec. Rotational control should
be set to 00b. 1x CD speed is 176.4 kbytes/sec. Speed is usually set to the
next lower possible value by the drive. So it is helpful to add a few
kbytes/sec just in case the drive has rounding problems.
(mmc5r03c.pdf 6.37)
A Write Parameters mode page 05h has to be composed and transmitted via
55h MODE SELECT. This page describes the following parameters:
BUFE Buffer Underrun protection 0=off, 1=on
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 02h = SAO
Multi-session Wether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 0 (is ignored)
Data Block Type Layout of payload blocks 0 (is ignored)
Audio Pause Length 150 = 2 seconds (ignored ?)
Any other parameters may be set to 0.
Mode page data as of MMC-5 table 644 are preceded by a Mode Parameter Header
as of SPC-3 table 240. This 8-byte header may be filled with zeros.
(mmc5r03c.pdf 7.5.4 The Mode Page, 4.2.3.4 Table 17 CONTROL = Track Mode)
(spc3r23.pdf 6.8 MODE SELECT, 7.4.3 Mode parameter header formats)
The Cue Sheet is submitted to the drive by 5Dh SEND CUE SHEET. Cue Sheet Size
is 8 times the number of entries.
(mmc5r03c.pdf 6.33)
Writing is performed by multiple 2Ah WRITE transactions with the Logical
Block Address counted up from the initial number in sync with the number of
blocks written. I.e the Transfer Length of the previous 2Ah WRITE has to be
added to the Logical Block Address for the next 2Ah WRITE. Only full blocks
can be written.
(mmc5r03c.pdf, 6.44)
Writing begins at LBA -150 which is to be transmitted as 4-byte, Big-endian,
two's-complement. E.g: -150 = FFh FFh FFh 6Ah. This is the natural form found
with about any 32-bit processor, so only the endianness has to be taken into
respect when converting a 32-bit integer into a LBA for command 2Ah WRITE.
At first the mandatory pause preceding the first track has to be written as
150 blocks of the matching sector size: 2048 for data, 2352 for audio.
By this, the LBA increases from -150 to 0.
Next the tracks' payload is sent. For each track exactly the number of blocks
has to be transmitted as is announced in the Cue Sheet by the difference
of the track's own start address and the start address of the next entry in
the Cue Sheet. After each write the LBA for the next write has to be increased
by the number of blocks transmitted. Just like with TAO writing.
There is no separator between the tracks of a pure mode SAO session.
(If the session was mixed mode, there would be extended Pre-gaps and Post-gaps
between data mode tracks and audio mode tracks.)
(libburn sends its own buffer to the drive at the end of each track but does
not sync the drive's chache. It is unclear wether this separation of tracks
on the level of 2Ah WRITE is necessary with a pure mode session. It does not
harm in any case and would probably be unavoidable if audio and data tracks
were mixed.)
When writing of all tracks is done, it is mandatory to force the drive's buffer
to media by 35h SYNCHRONIZE CACHE.
(mmc5r03c.pdf, 6.41)
No further finalization is necessary. (I.e. no 5Bh CLOSE TRACK SESSION.)
----------------------------------------------------------------------------
What is known about mixed mode sessions :
For now, SAO sessions with a mix of data and audio are not supported in
libburn. Here are the reasons why.
Obviously the code of http://icculus.org/burn is incomplete in this aspect.
In mmc5r03c.pdf comparison of table 555 and 6.33.3.18 seems self-contradicting.
(The second Pre-gap in table 555 does not match any of the criteria of
6.33.3.18. Also, there is no Post-gap shown in table 555 although 6.33.3.19
would prescribe some.)
If a data track follows an audio track then the data track gets a preceding
extended Pre-gap:
(CTL|ADR, TNO ,01h,DATA FORM,00h, MIN , SEC , FRAME)
with TNO already the number of the data track. The MSF address is to be
increased by 3 seconds. The first second of the extended Pre-gap needs to be
written in the audio track's mode and the other 2 seconds are to be written
in the data track's mode.
(libburn compares DATA FORM rather than burn_track.mode . Wrong ?)
(libburn currently does only 2 seconds and the second part of Pre-gap. There is
an issue with burn_track.pregap1 about this. Seems libburn mistakes the pause
preceding track 1 for a part 2 of an extended Pre-gap.)
If a data track is followed by an audio track then it gets a Post-gap of at
least two seconds.
No example of Post-gap is given for Cue Sheet. Maybe it is to be added to the
track, or maybe it gets an own Cue Sheet entry ... who knows ?
(libburn contains write code for pregap1, pregap2 and postgap. But only
pregap2 ever gets activated. Once hackingly for the first 2 second pause, once
incompletely for a change of DATA FORM.)
Seems nobody ever tested this. Libburnia simply knows no use case where the
correctness of Pre-gap and Post-gap would become evident.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Overwriteable DVD Cookbook
-------------------------------------------------------------------------------
Inspired by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
and by experiments with drives NEC ND-4570A and LG GSA-4082B.
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
Media type can be recognized by Current Profile from 46h GET CONFIGURATION.
(mmc5r03c.pdf 6.6.2.1)
DVD-RAM 0012h
DVD-RW Restricted Overwrite 0013h
DVD-RW Sequential Recording 0014h (i.e. unformatted)
DVD+RW 001Ah
A short compilation of the write model:
- Overwriting in general
The recipes described here are depending on formatting state:
- DVD-RAM, fully formatted DVD+RW or DVD-RW
- Unformatted DVD+RW
- Partly formatted DVD+RW
- Unformatted DVD-RW
- Partly formatted DVD-RW
- Intermediate state DVD-RW
-------------------------------------------------------------------------------
Overwriting in general :
Depending on media type, some kind of formatting has to have happened before
data can be written. Formatting may happen separately from writing or
simultaneously. See the particular recipes below.
No Write Parameters mode page 05h is to be sent. Speed can be influenced by
B6h SET STREAMING , speed capabilities can be inquired by ACh GET PERFORMANCE.
It is advised to set only speeds and sizes which are returned by ACh.
(mmc5r03c.pdf 6.39 SET STREAMING, 6.8 GET PERFORMANCE)
Optimal performance is promised without any speed setting. But my experiments
showed that SET STREAMING values persist after media change.
In the formatted area of the media, coarse random access is possible.
For DVD-RAM and DVD+RW write addresses and data size need to be aligned
to 2 KiB. For DVD-RW alignment has to be 32 KiB. Within these limitations
the write address is at the discretion of the sending program.
Just use 2Ah WRITE to send data.
(mmc5r03c.pdf, 6.44)
When writing is done, it is mandatory to force the drive's buffer to media by
35h SYNCHRONIZE CACHE.
(mmc5r03c.pdf, 6.41)
The size of the formatted area can be inquired by 23h READ FORMAT CAPACITIES.
The Number Of Blocks value in the Current/Maximum Capacity Descriptor gives
this size in 2 KiB blocks. But this is true only if Descriptor Type is 10b
("Formatted Media").
(mmc5r03c.pdf, 6.24.3.2.1, 6.24.3.2.3)
Not yet formatted areas may be completely forbidden or they may be allowed for
sequential writing (DVD-RW Intermediate state) or they may be allowed for
random access only after the necessary waiting time for formatting to reach
the desired address (DVD+RW with background formatting active).
Already written areas can be overwritten without special precaution.
Blanking a DVD-RW actually destroys its formatting.
Most of the concepts usually expressed in Write Parameters mode page 05h do not
apply to the recipes here: Test-Write, Buffer Underrun protection,
Multi-session, Write Type, Block Type, Track Mode, ...
There are hints for multi-session formats with DVD-RW but both of my drives
do not offer "Add Session" Format Types 12h or 14h.
(mmc5r03c.pdf 6.5.4.2.7 , 6.5.4.2.9)
Caution: Drive and media compatibility seems still to be quite an adventure.
If you experience problems, especially problems with readability, then try
different drives and media brands. Failure does not necessarily mean that the
software did anything wrong.
-------------------------------------------------------------------------------
DVD-RAM, fully formatted DVD+RW or DVD-RW :
Full format is the natural state of DVD-RAM.
DVD+RW reaches this state if Background Formatting is allowed to finish without
being stopped by 5Bh CLOSE TRACK SESSION.
(mmc5r03c.pdf, 6.5 FORMAT UNIT, 6.5.4.2.14 Format Type = 26h)
The formatting state of a DVD+RW may be inquired by 51h READ DISC INFORMATION
requesting Data Type 000b "Standard Disc Information". In the reply,
BG Format 3 indicates fully formatted media.
(mmc5r03c.pdf 6.22.3.1.13)
DVD-RW reaches this state either by Format Type 00h (or 10h) with maximum
size given as Number Of Blocks, or by writing sequentially until the disc is
completely full into an intermediate session opened by format 15h resp. 13h.
(mmc5r03c.pdf, 6.5 FORMAT UNIT, 6.5.4.2.1, 6.5.4.2.10, 6.5.4.2.8)
A fully formatted DVD-RW can be recognized by 23h READ FORMAT CAPACITIES. The
Descriptor Type of the Current/Maximum Capacity Descriptor is 10b ("Formatted
Media") and 0 blocks are offered with Format Types 13h or 11h.
(mmc5r03c.pdf, 6.24.3.2.1, 6.24.3.3)
See also discussion of unformatted or partially formatted DVD-RW below.
In fully formatted state there is no need for any formatting before writing nor
for any finalizing other than forcing the drive's buffer to media by
35h SYNCHRONIZE CACHE (which is mandatory for writing, anyway).
(mmc5r03c.pdf, 6.41)
(It seems to do no harm to send to DVD+RW or DVD-RW a 5Bh CLOSE TRACK SESSION
with Close Function 010b despite there is no session open in this scenario.)
-------------------------------------------------------------------------------
Unformatted DVD+RW
This is the state of previously unused DVD+RW media.
The formatting state of a DVD+RW may be inquired by 51h READ DISC INFORMATION
requiring Data Type 000b "Standard Disc Information".
In the reply, BG Format 0 indicates unformatted media (or unsuitable media).
(mmc5r03c.pdf 6.22.3.1.13)
Formatting has to be started by command 04h FORMAT UNIT, Format Type 26h.
Different from other format types, 26h allows to send a fantasy size of
0xffffffff blocks and does not require the caller to know the exact maximum
size offered with that format.
(mmc5r03c.pdf, 6.5 FORMAT UNIT, 6.5.4.2.14 Format Type = 26h)
As its name suggests, one has not to wait for background formatting to end
but may very soon start writing as on formatted media. Random access to
yet unformatted areas can last long, though.
If backup formatting has been started at the beginning of the session, then
it may get stopped after the final cache sync by 5Bh CLOSE TRACK SESSION
with Close Function 010b.
(mmc5r03c.pdf 6.3.3.6)
Formatting of DVD+RW is called "de-icing" because unformatted areas offer
no hold for random access addressing and are thus slippery like ice. One can
also see a color change from shiny unformatted to more dull formatted media.
-------------------------------------------------------------------------------
Partly formatted DVD+RW :
This state is achieved by stopping background formatting before the media
was completely formmatted.
The formatting state of a DVD+RW is obtained by 51h READ DISC INFORMATION
requiring Data Type 000b "Standard Disc Information".
In the reply, BG Format 1 indicates partly formatted media.
(mmc5r03c.pdf 6.22.3.1.13)
If the data of the session surely fit into the formatted area, then it would
be unnecessary to restart background formatting.
But in order to make the DVD+RW surely accept its maximum number of bytes,
formatting may be restarted by command 04h FORMAT UNIT, Format Type 26h,
with the Restart bit set and Number of Blocks set to 0xffffffff.
(mmc5r03c.pdf, 6.5 FORMAT UNIT, 6.5.4.2.14 Format Type = 26h)
From then on, the same rules apply as for previously unformatted DVD+RW.
-------------------------------------------------------------------------------
Unformatted DVD-RW (media profile is 0014h) :
This state is present with previously unused media. It is also present with
media blanked by programs cdrecord, wodim or dvd+rw-format and with media which
were sequentially written from blank state.
Profile transition from formatted 0013h to unformatted 0014h is done by
A1h BLANK.
(mmc5r03c.pdf, 6.2)
Experiments on my drives indicate that only Blanking Type 000b "Blank the disc"
achieves neat media. Media blanked via type 001b offer no feature 0021h and
stall cdrecord or libburn already when those media get examined. growisofs can
burn them - but only via DAO (feature 002Fh which prescribes Write Type 2).
(mmc5r03c.pdf 5.3.11, 5.3.25)
For becoming overwriteable such media need to be treated by command 04h FORMAT
UNIT.
(mmc5r03c.pdf, 6.5)
The Format Type has to be chosen from the list replied by 23h READ FORMAT
CAPACITIES. Suitable are Format Types 00h, 10h, 15h.
(mmc5r03c.pdf 6.24)
Format Types 00h and 10h provide a writeable area of a size given by Number of
Blocks. Type 00h seems to be the most traditional and complete one. It needs
no closing of a session at the end of writing.
The Number Of Blocks may be at most the value reported by 23h READ FORMAT
CAPACITIES in the entry for the desired format type. Full format is achieved
by sending exactly the reported value.
(mmc5r03c.pdf, 6.5.4.2.1 Format Type = 00h, 6.5.4.2.5 Format Type = 10h)
Format Type 15h provides a writeable area of given size too, but this area can
be expanded by sequential writing and afterwards marked as overwriteable by
closing the session. It is even allowed to format with size 0 and to leave
the size claim entirely to a sequential write process beginning at LBA 0.
(mmc5r03c.pdf, 6.5.4.2.10 Format Type = 15h)
When writing is done and cache is synced, one should send 5Bh CLOSE TRACK
SESSION with Close Function 010b in order to bring the session out of
Intermediate state.
(mmc5r03c.pdf 6.3.3.2.3)
If not written up to the last 32 KiB block, the DVD-RW is only partly formatted
after that.
-------------------------------------------------------------------------------
Partly formatted DVD-RW (media profile is 0013h) :
This state is achieved by formatting a DVD-RW with a number of blocks which
is less than offered for the Format Type by the drive's reply to 23h READ
FORMAT CAPACITIES. If the media was most recently formatted by Format Types
015h or 013h then it must have got written some bytes and afterwards treated
by 5Bh CLOSE TRACK SESSION, 010b in order to be partly formatted.
(mmc5r03c.pdf 6.3.3.2.3 CLOSE TRACK SESSION 010b, 6.24 READ FORMAT CAPACITIES)
Elsewise the media is in Intermediate state. See below.
A partly formatted DVD-RW can be recognized by 23h READ FORMAT CAPACITIES. The
Descriptor Type of the Current/Maximum Capacity Descriptor is 10b ("Formatted
Media") and the Number Of Blocks with formats 00h, 10h or 15h is larger than the
currently formatted size, resp. more than 0 blocks are offered with Format
Types 13h or 11h.
(mmc5r03c.pdf, 6.24.3.2.1, 6.24.3.3)
If the data of the session surely fit into the formatted area, then it would
be unnecessary to do any further formatting.
But in order to make the DVD-RW surely accept its maximum number of bytes,
partial formatting may be expanded by command 04h FORMAT UNIT, Format Type 13h,
which is supposed to be offered by the drive in this state. This brings the
session again into Intermediate state and thus allows expansion by sequential
writing. As with Format Type 15h it is ok to set Number Of Blocks to 0, so that
no fixed size formatting work is done and writing can begin soon after.
(mmc5r03c.pdf, 6.5.4.2.8 Format Type = 13h)
When writing is done and cache is synced, one should send 5Bh CLOSE TRACK
SESSION with Close Function 010b in order to bring the session out of
Intermediate state.
(mmc5r03c.pdf 6.3.3.2.3)
If not written up to the last 32 KiB block, the DVD-RW is only partly formatted
after that.
Format Type 13h has been tested only with expanding sessions formatted by 15h.
Nevertheless it is offered with sessions from 00h and 10h, too.
According to the specs, Format Type 11h would expand a session by a fixed
size. This has not been tested yet because it is less appealing than 13h.
(mmc5r03c.pdf, 6.5.4.2.6 Format Type = 11h)
-------------------------------------------------------------------------------
Intermediate state DVD-RW (media profile is 0013h) :
This state is achieved by formatting a DVD-RW with Format Type 15h or 13h
without subsequentially writing data and sending 5Bh CLOSE TRACK SESSION
with Close Function 010b.
Such media behave very unpleasing with my DVD-ROM drive under Linux 2.4 ide-cd.
One should therefore better avoid to release media in this state.
This state can be recognized by 23h READ FORMAT CAPACITIES. The Descriptor Type
of the Current/Maximum Capacity Descriptor is 11b ("Unknown Capacity") and
no formats 13h or 11h are offered.
(mmc5r03c.pdf, 6.24.3.2.1, 6.24.3.3)
One may treat such media as if Format Type 15h or 13h had been freshly applied.
I.e. sequential writing from LBA 0. After cache sync bring the session out
of Intermediate state by 5Bh CLOSE TRACK SESSION with Close Function 010b.
(mmc5r03c.pdf 6.3.3.2.3)
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Sequential DVD-R[W] Cookbook
-------------------------------------------------------------------------------
Inspired by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
and by experiments with drives NEC ND-4570A and LG GSA-4082B.
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
Media type can be recognized by Current Profile from 46h GET CONFIGURATION.
(mmc5r03c.pdf 6.6.2.1)
DVD-R 0011h
DVD-RW Restricted Overwrite 0013h
DVD-RW Sequential Recording 0014h
There are two approaches for writing to sequential DVD-R[W]: DAO and
Incremental. Not all media and drives offer Incremental which allows
multi-session as with CD media and does not demand a predicted track size.
DAO seems to be the older method. It allows only one single session and
track and it demands an exactly predicted track size.
- About overwriteable, blank, appendable and finalized DVD-R[W] media
- Incremental writing
- DAO writing
- Obtaining DVD-R[W] multi-session info for extending ISO-9660 filesystems
- Obtaining a Table Of Content from DVD-R[W]
-------------------------------------------------------------------------------
About overwriteable, blank, appendable and finalized DVD-R[W] media :
DVD-RW can be either in formatted state Restricted Overwrite or in unformatted
state Sequential Recording. Sequential media can be either blank, appendable
or finalized.
Only blank and appendable media are sequentially writeable. For overwriteable
DVD-RW see the Overwriteable DVD Cookbook.
Overwriteable DVD-RW can be detected by their profile number 0013h in contrast
to profile number 0014h for sequential DVD-RW.
The status of sequential media can be inquired like with CD by 51h READ DISC
INFORMATION requesting Data Type 000b Standard Disc Information, where reply
value Disc Status indicates:
00b blank
01b appendable
10b finalized
11b others (unsuitable for this recipe)
(mmc5r03c.pdf 6.22.3.1.4)
Finalized, appendable or overwriteable DVD-RW can be brought into blank
sequential state by command A1h BLANK with blanking type 000b "Blank the disc".
See TAO Multi-Session CD Cookbook for details about blanking.
After minimal blanking (type 001b) DVD-RW my two drives do not offer the
Incremental Streaming feature 0021h the media any more. Full blanking (000b)
brings back this feature.
(mmc5r03c.pdf 6.2)
-------------------------------------------------------------------------------
Incremental writing :
Incremental writing allows to produce multi-session DVDs. It is indicated
by feature 0021h being marked current in the reply of 46h GET CONFIGURATION.
growisofs inquires 0021h by setting Starting Feature Number to 0x21 and
Allocation Length to 16 in order to get only this one. The feature descriptor
begins at byte 8 of the reply. Its availability is indicated by the Current
Bit. libburn obtains the full feature list for this and other info.
(mmc5r03c.pdf 5.2.2. Feature Descriptor format, 5.3.11 Feature 0021h,
6.2 46h GET CONFIGURATION, )
In mode page 05h this method is selected by Write Type 00h.
Speed can be influenced by B6h SET STREAMING , speed capabilities can be
inquired by ACh GET PERFORMANCE. It is advised to set only speeds and sizes
which are returned by ACh.
(mmc5r03c.pdf 6.39 SET STREAMING, 6.8 GET PERFORMANCE)
growisofs fetches a mode page 05h template by MODE SENSE and inserts its own
parameters. It sets Multi-session to 11b, unless dvd_compat is nonzero.
libburn composes its mode page 05h from zero and allows control of
Multi-Session by the application.
BUFE Buffer Underrun protection 0=off, 1=on
LS_V Link size valid 1=true
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 00h = Incremental (Packet)
Multi-session Wether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 5 [*1]
Data Block Type Layout of payload blocks 8 [*2]
Link Size ??? 16 [*3]
FP Fixed Packet Size Bit 1
Packet Size 16 [*4]
(mmc5r03c.pdf 7.5.4 The Mode Page, 4.2.3.4 Table 17 CONTROL = Track Mode)
(spc3r23.pdf 6.8 MODE SELECT, 7.4.3 Mode parameter header formats)
[*1:]
growisofs takes the Track Mode from 52h READ TRACK INFORMATION, Address/Number
Type 1, Track 1, Track Information Block byte 5 & 0xf.
(mmc5r03.pdf 6.27)
The specs predict that this will be Track Mode 4 (6.27.3.8) and also state that
default is 5 (7.5.4.12). 4 means: uninterrupted, do not copy. 5 means
increment, do not copy.
[*2:]
8 means: 2048 byte data blocks. growisofs sets this value if Data Mode from
above 52h READ TRACK INFORMATION is 1 or Fh, which is predicted by the specs
to be always true.
(mmc5r03.pdf 6.27.3.10)
[*3:]
growisofs (transport.hxx) sets Link Size to 16 for profiles 0011h and 0014h.
libburn now records the first link size from feature 0021h in its burn_drive
structure. If another link size item is 16, then 16 is used.
[*4:]
growisofs takes Packet Size from 52h. Specs predict it will be 16 (= 32 kB).
(mmc5r03.pdf 7.5.4.16)
The writing process is much like in "Writing a session to CD in TAO mode" :
Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION.
libburn writes full 32 kB buffers via 2Ah WRITE.
(mmc5r03c.pdf, 6.27 READ TRACK INFORMATION, 6.44 WRITE)
When writing is done, it is mandatory to force the drive's buffer to media by
35h SYNCHRONIZE CACHE.
(mmc5r03c.pdf, 6.41)
The track has to be closed by 5Bh CLOSE TRACK SESSION Close Function 001b.
growisofs uses the logical track number for that and not FFh like libburn
does with TAO CD. So libburn obtains the Last Track Number in Last Session
from the reply of 51h READ DISC INFORMATION requesting Data Type 000b
"Standard Disc Information".
(mmc5r03c.pdf 6.3.3.2.2 CLOSE TRACK, 6.22.3.1.)
Multiple tracks are permissible in a single session. After all of them have
been written, 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track
Number 0 closes the session. It depends on the Multi-Session value in mode
page 05h wether the disc is finalized or stays appendable.
(mmc5r03c.pdf 6.3.3.2.3)
-------------------------------------------------------------------------------
DAO writing :
DAO is the mode described by feature 002Fh. This feature also gives information
about capabilities for Burnfree (BUF), Test Write and DVD-RW.
(mmc5r03c.pdf 5.3.25)
Experiments with growisofs showed that the track size needs to be predicted
and may not be exceeded during the write process. (growisofs ran into SCSI
errors with piped non-ISO-9660 images and with piped ISO-9660 which have
trailing data.)
Speed can be influenced by B6h SET STREAMING , speed capabilities can be
inquired by ACh GET PERFORMANCE. It is advised to set only speeds and sizes
which are returned by ACh.
(mmc5r03c.pdf 6.39 SET STREAMING, 6.8 GET PERFORMANCE)
The mode page 05h to be sent :
BUFE Buffer Underrun protection 0=off, 1=on
LS_V Link size valid 0=false [*3]
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 02h = DAO (same code as SAO)
Multi-session Wether to keep appendable 00b = finalize
Track Mode Describes frame type 5 [*1]
Data Block Type Layout of payload blocks 8 [*2]
Link Size ??? 0 [*3]
FP Fixed Packet Size Bit 0 [*3]
Packet Size 0 [*3]
(mmc5r03c.pdf 7.5.4 The Mode Page, 4.2.3.4 Table 17 CONTROL = Track Mode)
(spc3r23.pdf 6.8 MODE SELECT, 7.4.3 Mode parameter header formats)
[*1:]
growisofs takes the Track Mode from 52h READ TRACK INFORMATION, Address/Number
Type 1, Track 1, Track Information Block byte 5 & 0xf.
(mmc5r03.pdf 6.27)
[*2:]
8 means: 2048 byte data blocks. growisofs sets this value if Data Mode from
above 52h READ TRACK INFORMATION is 1 or Fh, which is predicted by the specs
to be always true. (If not: growisofs aborts.)
(mmc5r03.pdf 6.27.3.10)
[*3:]
Link Size, Packet Size and their companions only apply to Write Type 00h.
The session layout must be described by 53h RESERVE TRACK, RMZ=ARSV=0.
Reservation size should better already be aligned to 32 KiB. It has not been
tested yet, what happens if not enough data get written.
(mmc5r03c.pdf 6.31)
Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION.
The reply is supposed to be 0. libburn writes full 32 kB buffers via 2Ah WRITE.
(mmc5r03c.pdf, 6.27 READ TRACK INFORMATION, 6.44 WRITE)
If the track source delivers less than the announced size then libburn pads up
by zeros.
When writing is done, it is mandatory to force the drive's buffer to media by
35h SYNCHRONIZE CACHE.
(mmc5r03c.pdf, 6.41)
No further finalization is necessary. (I.e. no 5Bh CLOSE TRACK SESSION.)
-------------------------------------------------------------------------------
Obtaining DVD-R[W] multi-session info for extending ISO-9660 filesystems :
Like with CD it is necessary to obtain the two numbers for mkisofs option -C
in order to prepare a ISO-9660 filesystem image which by its inner pointers
matches the block addresses of the future location on media.
These are the start address of the first track in the last complete session
and the predicted start address of the track which will host the new image.
See TAO Multi-Session CD Cookbook for some more info about mkisofs aspects.
The first number may be gained by 43h READ TOC/PMA/ATIP Format 0001b which in
table 478 promises quick access via Start Address Of First Track In Last
Session.
(mmc5r03c.pdf 6.26.2.5 table 478, 6.26.3.3.1)
Regrettably the MMC-5 specs still define a useless reply for non-CD media
which obviously stems from MMC-3 times when no multi-session was possible
with non-CD.
(mmc5r03c.pdf 6.26.3.3.3)
Both my drives do give a useful reply with the correct number for appendable
DVD-RW. But not being backed by the specs this method appears unappealing .
Another approach would be a formatted Table of Content, obtained by 43h READ
TOC/PMA/ATIP Format 0000b. The specs do not totally outrule that this returns
useful data with non-CD but they define a crippled TOC for multi-session.
(mmc5r03c.pdf 6.26.3.2.4)
My LG drive returns a more detailed TOC, my NEC drive stays with the rather
suboptimal specs. So one would get different TOCs on different drives.
Nevertheless, the MMC-5 compliant TOC would return the desired number in
the Track Start address of the track with the highest number before AAh.
Most stable seems the approach to obtain the desired number from the reply
of 52h READ TRACK INFORMATION, Address/Number Type 01b. The field Logical Block
Address/Track/Session has to bear the track number of the first track in the
last complete session. To determine this number one has to determine the
number of the last session and the number of the last track from 51h READ DISC
INFORMATION and to iterate over the tracknumber by 52h READ TRACK INFORMATION
until the first track with the desired session number appears and reveils
its start address.
(mmc5r03c.pdf 6.22 51h DISC, 6.27 52h TRACK)
This method is very near to fabricating an own TOC. So libburn does this
when inspecting the media. If the first number for -C is needed, libburn
inquires its TOC model for the address of the first track in the last
complete session. See below for a detailed description of TOC fabrication.
The second -C number is the exact prediction of future track start address. It
is gained like with CD by 52h READ TRACK INFORMATION Type 01b. Different from
CD one may not use track number FFh but has to use the Last Track in Last
Session from 51h READ DISC INFORMATION.
(mmc5r03c.pdf 6.22 51h DISC, 6.27 52h TRACK)
-------------------------------------------------------------------------------
Obtaining a Table Of Content from DVD-R[W] :
The raw TOC entries from 43h READ TOC/PMA/ATIP Format 0010b as described with
CD media are not available with non-CD.
There is a Format 0000b "Formatted TOC" but this is with non-CD a fictional
information much at the discretion of the drive. Two drives with the same disc
may well return different Formatted TOC. They are supposed to be consistent
only about the last complete session and even there the MMC-5 specification
6.26.3.2.5 seems to prescribe a structure which does not match the true
structure of incremental writing to sequential DVD-R[W].
(mmc5r03c.pdf 6.26.3.2)
So i prefer not to use this method of getting a TOC.
The alternative is to produce an own TOC from information gained by 51h READ
DISC INFORMATION and by 52h READ TRACK INFORMATION which reveil a CD-like
structure of sessions and 1:n related tracks.
51h READ DISC INFORMATION Data Type 000b, fields Number of Sessions (Least
Significant Byte) and Number of Sessions (Most Significant Byte) give the
number of sessions. The last complete session number of an appendable disc
is one less because there is an incomplete session at its end. libburn only
records complete sessions in its TOC model.
libburn uses Last Track in Last Session as a hint for the range of track
numbers.
(mmc5r03c.pdf 6.22)
Next step is to iterate from 1 up to the last track number and to obtain
the according track info by 52h READ TRACK INFORMATION. Each track tells its
Session Number (LSB at byte 2, MSB at 33), its Logical Track Start Address,
its Logical Track Size, and much more which is not needed for a fake CD TOC.
One may analyze the track info more finely but for this special purpose
it is enough to discard the tracks which do not belong to complete sessions.
(mmc5r03c.pdf 6.27)
At the end of each session libburn inserts fake leadout entries into its TOC
model. Their start address is computed from the start and size of the last
track of the session.
-------------------------------------------------------------------------------

View File

@ -235,9 +235,11 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
/* ts A70103 moved up from burn_disc_erase_sync() */
/* ts A60825 : allow on parole to blank appendable CDs */
/* ts A70131 : allow blanking of overwriteable DVD-RW (profile 0x13) */
if ( ! (drive->status == BURN_DISC_FULL ||
(drive->status == BURN_DISC_APPENDABLE &&
! libburn_back_hack_42) ) ) {
! libburn_back_hack_42) ||
drive->current_profile == 0x13 ) ) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020130,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -323,6 +325,14 @@ static void *write_disc_worker_func(struct w_list *w)
void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
{
struct write_opts o;
int i, j, mode, mixed_mode = 0;
/* For the next lines any return indicates failure */
opts->drive->cancel = 1;
/* ts A70203 : people have been warned in API specs */
if (opts->write_type == BURN_WRITE_NONE)
return;
/* ts A61006 */
/* a ssert(!SCAN_GOING()); */
@ -347,6 +357,25 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
if (! burn_disc_write_is_ok(opts, disc)) /* issues own msgs */
return;
/* ts A70122 : libburn SAO code mishandles mode changes */
for (i = 0; i < disc->sessions; i++) {
if (disc->session[i]->tracks <= 0)
continue;
mode = disc->session[i]->track[0]->mode;
for (j = 1; j < disc->session[i]->tracks; j++)
if (mode != disc->session[i]->track[j]->mode)
mixed_mode = 1;
}
if (mixed_mode && opts->write_type == BURN_WRITE_SAO) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020133,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot mix data and audio in SAO mode", 0, 0);
return;
}
opts->drive->cancel = 0; /* End of the return = failure area */
o.drive = opts->drive;
o.opts = opts;
o.disc = disc;

View File

@ -347,6 +347,9 @@ int burn_drive_mark_unready(struct burn_drive *d)
/* ts A61202 */
d->current_profile = -1;
d->current_has_feat21h = 0;
d->current_feat2fh_byte4 = -1;
d->status = BURN_DISC_UNREADY;
if (d->toc_entry != NULL)
free(d->toc_entry);
@ -1406,6 +1409,32 @@ int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
}
/* ts A70131 : new API function */
int burn_disc_get_msc1(struct burn_drive *d, int *start)
{
int ret, trackno;
if (burn_drive_is_released(d)) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002011b,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Attempt to read track info from ungrabbed drive",
0, 0);
return -1;
}
if (d->busy != BURN_DRIVE_IDLE) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002011c,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Attempt to read track info from busy drive",
0, 0);
return -1;
}
ret = d->read_multi_session_c1(d, &trackno, start);
return ret;
}
/* ts A61202 : New API function */
int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80])
{
@ -1529,3 +1558,163 @@ int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list)
return burn_speed_descriptor_destroy(speed_list, 1);
}
/* ts A70203 : API function */
int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
struct burn_multi_caps **caps, int flag)
{
enum burn_disc_status s;
struct burn_multi_caps *o;
int status, num_formats, ret, type, i;
off_t size;
unsigned dummy;
*caps = NULL;
s = burn_disc_get_status(d);
if(s == BURN_DISC_UNGRABBED)
return -1;
*caps = o = (struct burn_multi_caps *)
malloc(sizeof(struct burn_multi_caps));
if(*caps == NULL)
return -1;
/* Default says nothing is available */
o->multi_session = o->multi_track = 0;
o-> start_adr = 0;
o->start_alignment = o->start_range_low = o->start_range_high = 0;
o->might_do_tao = o->might_do_sao = o->might_do_raw = 0;
o->advised_write_mode = BURN_WRITE_NONE;
o->selected_write_mode = wt;
o->current_profile = d->current_profile;
o->current_is_cd_profile = d->current_is_cd_profile;
if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) {
return 0;
} else if (s == BURN_DISC_APPENDABLE &&
(wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW)) {
return 0;
} else if (wt == BURN_WRITE_RAW && !d->current_is_cd_profile) {
return 0;
} else if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
/* CD-R , CD-RW */
if (d->block_types[BURN_WRITE_TAO]) {
o->multi_session = o->multi_track = 1;
o->might_do_tao = 2;
if (o->advised_write_mode == BURN_WRITE_NONE)
o->advised_write_mode = BURN_WRITE_TAO;
}
if (d->block_types[BURN_WRITE_SAO]) {
o->multi_session = o->multi_track = 1;
o->might_do_sao = 1;
if (o->advised_write_mode == BURN_WRITE_NONE)
o->advised_write_mode = BURN_WRITE_SAO;
}
if (d->block_types[BURN_WRITE_RAW]) {
o->might_do_raw = 1;
if (o->advised_write_mode == BURN_WRITE_NONE)
o->advised_write_mode = BURN_WRITE_RAW;
}
if (wt == BURN_WRITE_RAW)
o->multi_session = o->multi_track = 0;
} else if (d->current_profile == 0x11 || d->current_profile == 0x14) {
/* DVD-R , sequential DVD-RW */
if (s == BURN_DISC_BLANK) {
o->might_do_sao = 1;
o->advised_write_mode = BURN_WRITE_SAO;
}
if (d->current_has_feat21h) {
o->multi_session = o->multi_track = 1;
o->might_do_tao = 2;
o->advised_write_mode = BURN_WRITE_TAO;
}
if (wt == BURN_WRITE_SAO)
o->multi_session = o->multi_track = 0;
} else if (d->current_profile == 0x12 || d->current_profile == 0x13 ||
d->current_profile == 0x1a) {
/* DVD-RAM, overwriteable DVD-RW, DVD+RW */
o->start_adr = 1;
ret = burn_disc_get_formats(d, &status, &size, &dummy,
&num_formats);
if (ret == 1) {
if (status == BURN_FORMAT_IS_FORMATTED)
o->start_range_high = size;
if (d->current_profile == 0x13) {
o->start_alignment = 32 * 1024;
for (i = 0; i < num_formats; i++) {
ret = burn_disc_get_format_descr(d, i,
&type, &size, &dummy);
if (ret <= 0)
continue;
if (type == 0x13) /* expandable */
break;
}
if (i >= num_formats) /* not expandable */
o->start_range_high -= 32 * 1024;
} else {
o->start_alignment = 2 * 1024;
if (d->best_format_size - 2048 >
o->start_range_high)
o->start_range_high =
d->best_format_size - 2048;
}
}
o->might_do_tao = 2;
o->advised_write_mode = BURN_WRITE_TAO;
} else /* unknown media */
return 0;
if (s == BURN_DISC_APPENDABLE)
o->might_do_sao = o->might_do_raw = 0;
if (wt == BURN_WRITE_TAO && !o->might_do_tao)
return 0;
else if (wt == BURN_WRITE_SAO && !o->might_do_sao)
return 0;
else if (wt == BURN_WRITE_RAW && !o->might_do_raw)
return 0;
return 1;
}
/* ts A70203 : API function */
int burn_disc_free_multi_caps(struct burn_multi_caps **caps)
{
if (*caps == NULL)
return 0;
free((char *) *caps);
*caps = NULL;
return 1;
}
/* ts A70207 : evaluate write mode related peculiarities of a disc */
int burn_disc_get_write_mode_demands(struct burn_disc *disc,
struct burn_disc_mode_demands *result, int flag)
{
struct burn_session *session;
struct burn_track *track;
int i, j, mode;
memset((char *) result, 0, sizeof(struct burn_disc_mode_demands));
if (disc->sessions > 1)
result->multi_session = 1;
for (i = 0; i < disc->sessions; i++) {
session = disc->session[i];
if (session->tracks <= 0)
continue;
mode = session->track[0]->mode;
if (session->tracks > 1)
result->multi_track = 1;
for (j = 0; j < session->tracks; j++) {
track = session->track[j];
if (burn_track_is_open_ended(track))
result->unknown_track_size = 1;
if (mode != track->mode)
result->mixed_mode = 1;
if (track->mode != BURN_MODE1)
result->exotic_track = 1;
if (track->mode == BURN_AUDIO)
result->audio = 1;
}
}
return (disc->sessions > 0);
}

View File

@ -95,4 +95,17 @@ int burn_mdata_free_subs(struct scsi_mode_data *m);
/* ts A61230 */
void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag);
/* ts A70207 : evaluate write mode related peculiarities of a disc */
struct burn_disc_mode_demands {
int multi_session;
int multi_track;
int unknown_track_size;
int mixed_mode;
int audio;
int exotic_track;
};
int burn_disc_get_write_mode_demands(struct burn_disc *disc,
struct burn_disc_mode_demands *result, int flag);
#endif /* __DRIVE */

View File

@ -42,7 +42,7 @@ static int file_read(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fd *fs = source->data;
struct burn_source_file *fs = source->data;
return read_full_buffer(fs->datafd, buffer, size);
}
@ -71,14 +71,24 @@ static off_t file_size(struct burn_source *source)
struct stat buf;
struct burn_source_file *fs = source->data;
if (fs->fixed_size > 0)
return fs->fixed_size;
if (fstat(fs->datafd, &buf) == -1)
return (off_t) 0;
/* for now we keep it compatible to the old (int) return value */
if(buf.st_size >= 1308622848) /* 2 GB - 800 MB to prevent rollover */
return (off_t) 1308622848;
return (off_t) buf.st_size;
}
/* ts A70125 */
static int file_set_size(struct burn_source *source, off_t size)
{
struct burn_source_file *fs = source->data;
fs->fixed_size = size;
return 1;
}
struct burn_source *burn_file_source_new(const char *path, const char *subpath)
{
struct burn_source_file *fs;
@ -103,84 +113,43 @@ struct burn_source *burn_file_source_new(const char *path, const char *subpath)
if (subpath)
fs->subfd = fd2;
/* ts A70125 */
fs->fixed_size = 0;
src = burn_source_new();
src->read = file_read;
if (subpath)
src->read_sub = file_read_sub;
src->get_size = file_size;
src->set_size = file_set_size;
src->free_data = file_free;
src->data = fs;
return src;
}
/* ------ provisory location for the new source subclass fd --------- */
static off_t fd_get_size(struct burn_source *source)
{
struct stat buf;
struct burn_source_fd *fs = source->data;
if (fs->fixed_size > 0)
return fs->fixed_size;
if (fstat(fs->datafd, &buf) == -1)
return (off_t) 0;
/* for now we keep it compatible to the old (int) return value */
if (buf.st_size >= 1308622848) /* 2 GB - 800 MB to prevent rollover */
return (off_t) 1308622848;
return buf.st_size;
}
static int fd_read(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fd *fs = source->data;
return read_full_buffer(fs->datafd, buffer, size);
}
static int fd_read_sub(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fd *fs = source->data;
return read_full_buffer(fs->subfd, buffer, size);
}
static void fd_free_data(struct burn_source *source)
{
struct burn_source_fd *fs = source->data;
close(fs->datafd);
if (source->read_sub)
close(fs->subfd);
free(fs);
}
/* ts A70126 : removed class burn_source_fd in favor of burn_source_file */
struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
{
struct burn_source_fd *fs;
struct burn_source_file *fs;
struct burn_source *src;
if (datafd == -1)
return NULL;
fs = malloc(sizeof(struct burn_source_fd));
fs = malloc(sizeof(struct burn_source_file));
fs->datafd = datafd;
fs->subfd = subfd;
fs->fixed_size = size;
src = burn_source_new();
src->read = fd_read;
src->read = file_read;
if(subfd != -1)
src->read = fd_read_sub;
src->get_size = fd_get_size;
src->free_data = fd_free_data;
src->read = file_read_sub;
src->get_size = file_size;
src->set_size = file_set_size;
src->free_data = file_free;
src->data = fs;
return src;
}

View File

@ -4,19 +4,14 @@
#define BURN__FILE_H
struct burn_source_file
{
int datafd;
int subfd;
};
/* ------ provisory location for the new source subclass fd --------- */
struct burn_source_fd
{
int datafd;
int subfd;
off_t fixed_size;
};
/* ts A70126 : burn_source_file obsoleted burn_source_fd */
#endif /* LIBBURN__FILE_H */

View File

@ -107,22 +107,40 @@ struct burn_write_opts;
enum burn_write_types
{
/** Packet writing.
currently unsupported
currently unsupported, (for DVD Incremental Streaming use TAO)
*/
BURN_WRITE_PACKET,
/** Track At Once recording.
2s gaps between tracks, no fonky lead-ins
/** With CD: Track At Once recording
2s gaps between tracks, no fonky lead-ins
With sequential DVD-R[W]: Incremental Streaming
With DVD-RAM/+RW: Random Writeable (used sequentially)
With overwriteable DVD-RW: Rigid Restricted Overwrite
*/
BURN_WRITE_TAO,
/** Session At Once.
block type MUST be BURN_BLOCK_SAO
/** With CD: Session At Once
Block type MUST be BURN_BLOCK_SAO
ts A70122: Currently not capable of mixing data and audio tracks.
With sequential DVD-R[W]: Disc-at-once, DAO
Single session, single track, fixed size mandatory, (-dvd-compat)
*/
BURN_WRITE_SAO,
/** Raw disc at once recording.
all subcodes must be provided by lib or user
only raw block types are supported
/** With CD: Raw disc at once recording.
all subcodes must be provided by lib or user
only raw block types are supported
*/
BURN_WRITE_RAW
BURN_WRITE_RAW,
/** In replies this indicates that not any writing will work.
As parameter for inquiries it indicates that no particular write
mode shall is specified.
Do not use for setting a write mode for burning. It won't work.
*/
BURN_WRITE_NONE
};
/** Data format to send to the drive */
@ -237,9 +255,18 @@ enum burn_drive_status
};
/** Information about a track on a disc - this is from the q sub channel of the
lead-in area of a disc. The documentation here is very terse.
See a document such as mmc3 for proper information.
CAUTION : This structure is prone to future extension !
Do not restrict your application to unsigned char with any counter like
"session", "point", "pmin", ...
Do not rely on the current size of a burn_toc_entry.
ts A70201 : DVD extension, see below
*/
struct burn_toc_entry
{
@ -263,6 +290,23 @@ struct burn_toc_entry
unsigned char psec;
/** Track start time frames for normal tracks */
unsigned char pframe;
/* Indicates wether extension data are valid and eventually override
older elements in this structure:
bit0= DVD extension is valid
*/
unsigned char extensions_valid;
/* ts A70201 : DVD extension.
If invalid the members are guaranteed to be 0. */
/* Tracks and session numbers are 16 bit. Here are the high bytes. */
unsigned char session_msb;
unsigned char point_msb;
/* pmin, psec, and pframe may be too small if DVD extension is valid */
int start_lba;
/* min, sec, and frame may be too small if DVD extension is valid */
int track_blocks;
};
@ -286,6 +330,9 @@ struct burn_source {
/** Get the size of the source's data */
off_t (*get_size)(struct burn_source *);
/** Set the size of the source's data */
int (*set_size)(struct burn_source *source, off_t size);
/** Clean up the source specific data */
void (*free_data)(struct burn_source *);
@ -781,6 +828,16 @@ int burn_drive_get_start_end_lba(struct burn_drive *drive,
int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
int trackno, int *lba, int *nwa);
/* ts A70131 */
/** Read start lba of the first track in the last complete session.
This is the first parameter of mkisofs option -C. The second parameter
is nwa as obtained by burn_disc_track_lba_nwa() with trackno 0.
@param d The drive to query.
@param start_lba returns the start address of that track
@return <= 0 : failure, 1 = ok
*/
int burn_disc_get_msc1(struct burn_drive *d, int *start_lba);
/* ts A61202 */
/** Tells the MMC Profile identifier of the loaded media. The drive must be
grabbed in order to get a non-zero result.
@ -925,6 +982,9 @@ void burn_disc_read(struct burn_drive *drive, const struct burn_read_opts *o);
/** Write a disc in the drive. The drive must be grabbed successfully before
calling this function. Always ensure that the drive reports a status of
BURN_DISC_BLANK before calling this function.
Note: write_type BURN_WRITE_SAO is currently not capable of writing a mix
of data and audio tracks. You must use BURN_WRITE_TAO for such sessions.
To be set by burn_write_opts_set_write_type().
@param o The options for the writing operation.
@param disc The struct burn_disc * that described the disc to be created
*/
@ -980,7 +1040,7 @@ int burn_msf_to_lba(int m, int s, int f);
*/
void burn_lba_to_msf(int lba, int *m, int *s, int *f);
/** Create a new disc (for DAO recording)*/
/** Create a new disc */
struct burn_disc *burn_disc_create(void);
/** Delete disc and decrease the reference count on all its sessions
@ -988,9 +1048,7 @@ struct burn_disc *burn_disc_create(void);
*/
void burn_disc_free(struct burn_disc *d);
/** Create a new session (For SAO at once recording, or to be added to a
disc for DAO)
*/
/** Create a new session */
struct burn_session *burn_session_create(void);
/** Free a session (and decrease reference count on all tracks inside)
@ -1145,7 +1203,9 @@ void burn_structure_print_disc(struct burn_disc *d);
void burn_structure_print_session(struct burn_session *s);
void burn_structure_print_track(struct burn_track *t);
/** Sets the write type for the write_opts struct
/** Sets the write type for the write_opts struct.
Note: write_type BURN_WRITE_SAO is currently not capable of writing a mix
of data and audio tracks. You must use BURN_WRITE_TAO for such sessions.
@param opts The write opts to change
@param write_type The write type to use
@param block_type The block type to use
@ -1155,6 +1215,22 @@ int burn_write_opts_set_write_type(struct burn_write_opts *opts,
enum burn_write_types write_type,
int block_type);
/* ts A70207 */
/** As an alternative to burn_write_opts_set_write_type() this function tries
to find a suitable write type and block type for a given write job
described by opts and disc. To be used after all other setups have been
made, i.e. immediately before burn_disc_write().
@param opts The nearly complete write opts to change
@param disc The already composed session and track model
@param reasons This text string collects reasons for decision resp. failure
@param flag Bitfield for control purposes (unused yet, submit 0)
@return Chosen write type. BURN_WRITE_NONE on failure.
*/
enum burn_write_types burn_write_opts_auto_write_type(
struct burn_write_opts *opts, struct burn_disc *disc,
char reasons[1024], int flag);
/** Supplies toc entries for writing - not normally required for cd mastering
@param opts The write opts to change
@param count The number of entries
@ -1208,11 +1284,11 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi);
/* ts A61222 */
/** Sets a start address for writing to media and write modes which allow to
choose this address at all (DVD+RW, DVD-RAM, DVD-RW only for now). The
address is given in bytes. If it is not -1 then a write run will fail if
choice of start address is not supported or if the block alignment of the
address is not suitable for media and write mode. (Alignment to 32 kB
blocks is advised with DVD media.)
choose this address at all (DVD+RW, DVD-RAM, formatted DVD-RW only for
now). The address is given in bytes. If it is not -1 then a write run
will fail if choice of start address is not supported or if the block
alignment of the address is not suitable for media and write mode.
(Alignment to 32 kB blocks is advised with DVD media.)
@param opts The write opts to change
@param value The address in bytes (-1 = start at default address)
*/
@ -1324,6 +1400,105 @@ int burn_drive_get_speedlist(struct burn_drive *d,
int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list);
/* ts A70203 */
/** The reply structure for burn_disc_get_multi_caps()
*/
struct burn_multi_caps {
/* Multi-session capability allows to keep the media appendable after
writing a session. It also guarantees that the drive will be able
to predict and use the appropriate Next Writeable Address to place
the next session on the media without overwriting the existing ones.
It does not guarantee that the selected write type is able to do
an appending session after the next session. (E.g. CD SAO is capable
of multi-session by keeping a disc appendable. But .might_do_sao
will be 0 afterwards, when checking the appendable media.)
1= media may be kept appendable by burn_write_opts_set_multi(o,1)
0= media will not be apendable appendable
*/
int multi_session;
/* Multi-track capability allows to write more than one track source
during a single session. The written tracks can later be found in
libburn's TOC model with their start addresses and sizes.
1= multiple tracks per session are allowed
0= only one track per session allowed
*/
int multi_track;
/* Start-address capability allows to set a non-zero address with
burn_write_opts_set_start_byte(). Eventually this has to respect
.start_alignment and .start_range_low, .start_range_high in this
structure.
1= non-zero start address is allowed
0= only start address 0 is allowed (to depict the drive's own idea
about the appropriate write start)
*/
int start_adr;
/** The alignment for start addresses.
( start_address % start_alignment ) must be 0.
*/
off_t start_alignment;
/** The lowest permissible start address.
*/
off_t start_range_low;
/** The highest addressable start address.
*/
off_t start_range_high;
/** Potential availability of write modes
2= available, no size prediction necessary
1= available, needs exact size prediction
0= not available
With CD media (profiles 0x09 and 0x0a) check also the elements
*_block_types of the according write mode.
*/
int might_do_tao;
int might_do_sao;
int might_do_raw;
/** Advised write mode.
*/
enum burn_write_types advised_write_mode;
/** Write mode as given by parameter wt of burn_disc_get_multi_caps().
*/
enum burn_write_types selected_write_mode;
/** Profile number which was current when the reply was generated */
int current_profile;
/** Wether the current profile indicates CD media. 1=yes, 0=no */
int current_is_cd_profile;
};
/** Allocates a struct burn_multi_caps (see above) and fills it with values
which are appropriate for the drive and the loaded media. The drive
must be grabbed for this call. The returned structure has to be disposed
via burn_disc_free_multi_caps() when no longer needed.
@param d The drive to inquire
@param wt With BURN_WRITE_NONE the best capabilities of all write modes
get returned. If set to a write mode like BURN_WRITE_SAO the
capabilities with that particular mode are returned and the
return value is 0 if the desired mode is not possible.
@param caps returns the info structure
@param flag Bitfield for control purposes (unused yet, submit 0)
@return < 0 : error , 0 : writing seems impossible , 1 : writing possible
*/
int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
struct burn_multi_caps **caps, int flag);
/** Removes from memory a multi session info structure which was returned by
burn_disc_get_multi_caps(). The pointer *caps gets set o NULL.
@param caps the info structure to dispose (note: pointer to pointer)
@return 0 : *caps was already NULL, 1 : memory object was disposed
*/
int burn_disc_free_multi_caps(struct burn_multi_caps **caps);
/** Gets a copy of the toc_entry structure associated with a track
@param t Track to get the entry from
@param entry Struct for the library to fill out

View File

@ -1,7 +1,8 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006-2007 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL
*/
@ -347,8 +348,18 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020127 (NOTE,HIGH) = Write start address is ...
0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance
0x00020129 (SORRY,HIGH) = Will not format media type
0x0002012a (FATAL,HIGH) = Cannot inquire write mode capabilities
0x0002012b (FATAL,HIGH) = Drive offers no suitable write mode with this job
0x00020130 (SORRY,HIGH) = Drive and media state unsuitable for blanking
0x00020131 (SORRY,HIGH) = No suitable formatting type offered by drive
0x00020132 (SORRY,HIGH) = Selected format is not suitable for libburn
0x00020133 (SORRY,HIGH) = Cannot mix data and audio in SAO mode
0x00020134 (NOTE,HIGH) = Defaulted TAO to DAO
0x00020135 (SORRY,HIGH) = Cannot perform TAO, job unsuitable for DAO
0x00020136 (SORRY,HIGH) = DAO Burning restricted to single fixed size track
0x00020137 (HINT,HIGH) = TAO would be possible
0x00020138 (FATAL,HIGH) = Cannot reserve track
libdax_audioxtr:

View File

@ -44,7 +44,12 @@ extern struct libdax_msgs *libdax_messenger;
#define Libburn_support_dvd_raM 1
/* Progress report (with Libburn_support_dvd_plus_rW defined):
/* ts A70129 >>> EXPERIMENTAL UNTESTED
*/
#define Libburn_support_dvd_r_seQ 1
/* Progress report:
ts A61219 : It seems to work with a used (i.e. thoroughly formatted) DVD+RW.
Error messages of class DEBUG appear because of inability to
read TOC or track info. Nevertheless, the written images verify.
@ -65,12 +70,27 @@ extern struct libdax_msgs *libdax_messenger;
ts A70101 : Formatted DVD-RW media. Success is varying with media, but
dvd+rw-format does not do better with the same media.
ts A70112 : Support for writing to DVD-RAM.
ts A70130 : Burned a first non-multi sequential DVD-RW. Feature 0021h
Incremental Recording vanishes after that and media thus gets
not recognized as suitable any more.
After a run with -multi another disc still offers 0021h .
dvd+rw-mediainfo shows two tracks. The second, an afio archive
is readable by afio. Third and forth veryfy too. Suddenly
dvd+rw-mediainfo sees lba 0 with track 2. But #2 still verifies
if one knows its address.
ts A70203 : DVD-RW need to get blanked fully. Then feature 0021h persists.
Meanwhile Incremental streaming is supported like CD TAO:
with unpredicted size, multi-track, multi-session.
ts A70205 : Beginning to implement DVD-R[W] DAO : single track and session,
size prediction mandatory.
Todo:
Determine first free lba for appending data.
Determine first free lba for appending data on overwriteables.
*/
static unsigned char MMC_GET_MSINFO[] =
{ 0x43, 0, 1, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_TOC[] = { 0x43, 2, 2, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_ATIP[] = { 0x43, 2, 4, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_DISC_INFO[] =
@ -116,6 +136,10 @@ static unsigned char MMC_GET_PERFORMANCE[] =
static unsigned char MMC_READ_FORMAT_CAPACITIES[] =
{ 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/* ts A70205 : To describe the layout of a DVD-R[W] DAO session */
static unsigned char MMC_RESERVE_TRACK[] =
{ 0x53, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int mmc_function_spy_do_tell = 0;
@ -135,6 +159,25 @@ int mmc_function_spy_ctrl(int do_tell)
}
/* ts A70201 */
int mmc_four_char_to_int(unsigned char *data)
{
return (data[0] << 24) | (data[1] << 16) |
(data[2] << 8) | data[3];
}
/* ts A70201 */
int mmc_int_to_four_char(unsigned char *data, int num)
{
data[0] = (num >> 24) & 0xff;
data[1] = (num >> 16) & 0xff;
data[2] = (num >> 8) & 0xff;
data[3] = num & 0xff;
return 1;
}
void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
{
struct buffer buf;
@ -156,15 +199,48 @@ void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
d->issue_command(d, &c);
}
/* ts A61110 : added parameters trackno, lba, nwa. Redefined return value.
@return 1=nwa is valid , 0=nwa is not valid , -1=error */
int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
{
struct buffer buf;
struct command c;
unsigned char *data;
mmc_function_spy("mmc_get_nwa");
/* ts A70205 : Announce size of a DVD-R[W] DAO session.
@param size The size in bytes to be announced to the drive.
It will get rounded up to align to 32 KiB.
*/
int mmc_reserve_track(struct burn_drive *d, off_t size)
{
struct command c;
int lba;
char msg[80];
mmc_function_spy("mmc_reserve_track");
c.retry = 1;
c.oplen = sizeof(MMC_RESERVE_TRACK);
memcpy(c.opcode, MMC_RESERVE_TRACK, sizeof(MMC_RESERVE_TRACK));
/* Round to 32 KiB and divide by 2048
(by nice binary rounding trick learned from dvd+rw-tools) */
lba = ((size + (off_t) 0x7fff) >> 11) & ~0xf;
mmc_int_to_four_char(c.opcode+5, lba);
sprintf(msg, "reserving track of %d blocks", lba);
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msg, 0, 0);
c.page = NULL;
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
return !c.error;
}
/* ts A70201 :
Common track info fetcher for mmc_get_nwa() and mmc_fake_toc()
*/
int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf)
{
struct command c;
int i;
mmc_function_spy("mmc_read_track_info");
c.retry = 1;
c.oplen = sizeof(MMC_TRACK_INFO);
memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
@ -173,16 +249,76 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12 )
/* DVD+RW , DVD-RW restricted overwrite , DVD-RAM */
c.opcode[5] = 1;
trackno = 1;
else if (d->current_profile == 0x11 ||
d->current_profile == 0x14) /* DVD-R[W] Sequential */
trackno = d->last_track_no;
else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
c.opcode[5] = 0xFF;
} else
c.opcode[5] = trackno;
trackno = 0xFF;
}
for (i = 0; i < 4; i++)
c.opcode[2 + i] = (trackno >> (24 - 8 * i)) & 0xff;
c.page = buf;
memset(buf->data, 0, BUFFER_SIZE);
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
if (c.error)
return 0;
return 1;
}
/* ts A61110 : added parameters trackno, lba, nwa. Redefined return value.
@return 1=nwa is valid , 0=nwa is not valid , -1=error */
/* ts A70201 : outsourced 52h READ TRACK INFO command */
int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
{
struct buffer buf;
int ret;
#ifdef Libburn_get_nwa_standalonE
struct command c;
int i;
#endif
unsigned char *data;
mmc_function_spy("mmc_get_nwa");
if(trackno<=0) {
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12 )
/* DVD+RW , DVD-RW restricted overwrite , DVD-RAM */
trackno = 1;
else if (d->current_profile == 0x11 ||
d->current_profile == 0x14) /* DVD-R[W] Sequential */
trackno = d->last_track_no;
else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
trackno = 0xFF;
}
#ifdef Libburn_get_nwa_standalonE
c.retry = 1;
c.oplen = sizeof(MMC_TRACK_INFO);
memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
c.opcode[1] = 1;
for (i = 0; i < 4; i++)
c.opcode[2 + i] = (trackno >> (24 - 8 * i)) & 0xff;
c.page = &buf;
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
data = c.page->data;
#else /* Libburn_get_nwa_standalonE */
ret = mmc_read_track_info(d, trackno, &buf);
if (ret <= 0)
return ret;
data = buf.data;
#endif /* ! Libburn_get_nwa_standalonE */
*lba = (data[8] << 24) + (data[9] << 16)
+ (data[10] << 8) + data[11];
*nwa = (data[12] << 24) + (data[13] << 16)
@ -254,7 +390,6 @@ void mmc_close(struct burn_drive *d, int session, int track)
/* ts A61030 : shifted !!session rather than or-ing plain session */
c.opcode[2] = ((!!session)<<1) | !!track;
c.opcode[4] = track >> 8;
c.opcode[5] = track & 0xFF;
c.page = NULL;
@ -391,9 +526,166 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
return 0;
}
/* ts A70201 : Set up an entry for mmc_fake_toc() */
int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
int track_number,
unsigned char *size_data, unsigned char *start_data)
{
int min, sec, frames, num;
/* mark DVD extensions as valid */
entry->extensions_valid |= 1;
/* defaults are as of mmc5r03.pdf 6.26.3.2.4 Fabricated TOC */
entry->session = session_number & 0xff;
entry->session_msb = (session_number >> 8) & 0xff;
entry->adr = 1;
entry->control = 4;
entry->tno = 0;
entry->point = track_number & 0xff;
entry->point_msb = (track_number >> 8) & 0xff;
num = (size_data[0] << 24) | (size_data[1] << 16) |
(size_data[2] << 8) | size_data[3];
entry->track_blocks = num;
burn_lba_to_msf(num, &min, &sec, &frames);
if (min > 255) {
min = 255;
sec = 255;
frames = 255;
}
entry->min = min;
entry->sec = sec;
entry->frame = frames;
entry->zero = 0;
num = (start_data[0] << 24) | (start_data[1] << 16) |
(start_data[2] << 8) | start_data[3];
entry->start_lba = num;
burn_lba_to_msf(num, &min, &sec, &frames);
if (min > 255) {
min = 255;
sec = 255;
frames = 255;
}
entry->pmin = min;
entry->psec = sec;
entry->pframe = frames;
return 1;
}
/* ts A70131 : compose a disc TOC structure from d->complete_sessions
and 52h READ TRACK INFORMATION */
int mmc_fake_toc(struct burn_drive *d)
{
struct burn_track *track;
struct burn_session *session;
struct burn_toc_entry *entry;
struct buffer buf;
int i, session_number, prev_session = -1, ret, lba;
unsigned char *tdata, size_data[4], start_data[4];
if (d->last_track_no <= 0 || d->complete_sessions <= 0 ||
d->status == BURN_DISC_BLANK)
return 2;
d->disc = burn_disc_create();
if (d->disc == NULL)
return -1;
d->toc_entries = d->last_track_no + d->complete_sessions;
d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry));
if (d->toc_entry == NULL)
return -1;
memset(d->toc_entry, 0,d->toc_entries * sizeof(struct burn_toc_entry));
for (i = 0; i < d->complete_sessions; i++) {
session = burn_session_create();
burn_disc_add_session(d->disc, session, BURN_POS_END);
burn_session_free(session);
}
memset(size_data, 0, 4);
memset(start_data, 0, 4);
/* Entry Layout :
session 1 track 1 entry 0
...
session 1 track N entry N-1
leadout 1 entry N
session 2 track N+1 entry N+1
...
session 2 track M+1 entry M+1
leadout 2 entry M+2
session X track K entry (K-1)+(X-1)
...
session X track i+1 entry i+(X-1)
leadout X entry i+X
*/
for (i = 0; i < d->last_track_no; i++) {
ret = mmc_read_track_info(d, i+1, &buf);
if (ret < 0)
return ret;
if (ret == 0)
continue;
tdata = buf.data;
session_number = (tdata[33] << 8) | tdata[3];
if (session_number <= 0)
continue;
if (session_number != prev_session && prev_session > 0) {
/* leadout entry previous session */
entry = &(d->toc_entry[(i - 1) + prev_session]);
lba = mmc_four_char_to_int(start_data) +
mmc_four_char_to_int(size_data);
mmc_int_to_four_char(start_data, lba);
mmc_int_to_four_char(size_data, 0);
mmc_fake_toc_entry(entry, prev_session, 0xA2,
size_data, start_data);
entry->min= entry->sec= entry->frame= 0;
d->disc->session[prev_session - 1]->leadout_entry =
entry;
}
if (session_number > d->disc->sessions)
continue;
entry = &(d->toc_entry[i + session_number - 1]);
track = burn_track_create();
if (track == NULL)
return -1;
burn_session_add_track(
d->disc->session[session_number - 1],
track, BURN_POS_END);
track->entry = entry;
burn_track_free(track);
memcpy(size_data, tdata + 24, 4);
memcpy(start_data, tdata + 8, 4);
mmc_fake_toc_entry(entry, session_number, i + 1,
size_data, start_data);
if (prev_session != session_number)
d->disc->session[session_number - 1]->firsttrack = i+1;
d->disc->session[session_number - 1]->lasttrack = i+1;
prev_session = session_number;
}
if (prev_session > 0 && prev_session <= d->disc->sessions) {
/* leadout entry of last session of closed disc */
entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]);
lba = mmc_four_char_to_int(start_data) +
mmc_four_char_to_int(size_data);
mmc_int_to_four_char(start_data, lba);
mmc_int_to_four_char(size_data, 0);
mmc_fake_toc_entry(entry, prev_session, 0xA2,
size_data, start_data);
entry->min= entry->sec= entry->frame= 0;
d->disc->session[prev_session - 1]->leadout_entry = entry;
}
return 1;
}
void mmc_read_toc(struct burn_drive *d)
{
/* read full toc, all sessions, in m/s/f form, 4k buffer */
/* ts A70201 : or fake a toc from track information */
struct burn_track *track;
struct burn_session *session;
struct buffer buf;
@ -403,6 +695,23 @@ void mmc_read_toc(struct burn_drive *d)
unsigned char *tdata;
mmc_function_spy("mmc_read_toc");
if (!(d->current_profile == -1 || d->current_is_cd_profile)) {
/* ts A70131 : MMC_GET_TOC uses Response Format 2
For DVD this fails with 5,24,00 */
/* One could try Response Format 0: mmc5r03.pdf 6.26.3.2
which does not yield the same result wit the same disc
on different drives.
*/
/* ts A70201 :
This uses the session count from 51h READ DISC INFORMATION
and the track records from 52h READ TRACK INFORMATION
*/
mmc_fake_toc(d);
if (d->status == BURN_DISC_UNREADY)
d->status = BURN_DISC_FULL;
return;
}
memcpy(c.opcode, MMC_GET_TOC, sizeof(MMC_GET_TOC));
c.retry = 1;
c.oplen = sizeof(MMC_GET_TOC);
@ -425,11 +734,12 @@ void mmc_read_toc(struct burn_drive *d)
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002010d,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Could not inquire TOC (non-blank DVD media ?)", 0,0);
"Could not inquire TOC", 0,0);
d->status = BURN_DISC_UNSUITABLE;
d->toc_entries = 0;
/* Prefering memory leaks over fandangos */
d->toc_entry = malloc(sizeof(struct burn_toc_entry));
memset(&(d->toc_entry[0]), 0, sizeof(struct burn_toc_entry));
return;
}
@ -443,6 +753,8 @@ void mmc_read_toc(struct burn_drive *d)
a ssert(((dlen - 2) % 11) == 0);
*/
d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry));
for (i = 0; i < d->toc_entries; i++)
memset(&(d->toc_entry[i]), 0, sizeof(struct burn_toc_entry));
tdata = c.page->data + 4;
burn_print(12, "TOC:\n");
@ -466,8 +778,7 @@ void mmc_read_toc(struct burn_drive *d)
burn_print(bpl, " MSF(%d:%d:%d)", tdata[4],tdata[5],tdata[6]);
burn_print(bpl, " PMSF(%d:%d:%d %d)",
tdata[8], tdata[9], tdata[10],
burn_msf_to_lba(tdata[8], tdata[9], tdata[10])
);
burn_msf_to_lba(tdata[8], tdata[9], tdata[10]));
burn_print(bpl, " - control %d, adr %d\n", tdata[1] & 0xF,
tdata[1] >> 4);
@ -519,21 +830,98 @@ void mmc_read_toc(struct burn_drive *d)
/* ts A61022 */
burn_print(bpl, "-----------------------------------\n");
if (d->status != BURN_DISC_APPENDABLE)
/* ts A70131 : was (d->status != BURN_DISC_BLANK) */
if (d->status == BURN_DISC_UNREADY)
d->status = BURN_DISC_FULL;
toc_find_modes(d);
}
/* ts A70131 : This tries to get the start of the last complete session */
/* man mkisofs , option -C :
The first number is the sector number of the first sector in
the last session of the disk that should be appended to.
*/
int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
{
struct buffer buf;
struct command c;
unsigned char *tdata;
int num_sessions, session_no, num_tracks;
struct burn_disc *disc;
struct burn_session **sessions;
struct burn_track **tracks;
struct burn_toc_entry toc_entry;
mmc_function_spy("mmc_read_multi_session_c1");
/* First try to evaluate the eventually loaded TOC before issueing
a MMC command. This search obtains the first track of the last
complete session which has a track.
*/
*trackno = 0;
disc = burn_drive_get_disc(d);
if (disc == NULL)
goto inquire_drive;
sessions = burn_disc_get_sessions(disc, &num_sessions);
for (session_no = 0; session_no<num_sessions; session_no++) {
tracks = burn_session_get_tracks(sessions[session_no],
&num_tracks);
if (tracks == NULL || num_tracks <= 0)
continue;
burn_track_get_entry(tracks[0], &toc_entry);
if (toc_entry.extensions_valid & 1) { /* DVD extension valid */
*start = toc_entry.start_lba;
*trackno = (toc_entry.point_msb << 8)| toc_entry.point;
} else {
*start = burn_msf_to_lba(toc_entry.pmin,
toc_entry.psec, toc_entry.pframe);
*trackno = toc_entry.point;
}
}
burn_disc_free(disc);
if(*trackno > 0)
return 1;
inquire_drive:;
/* mmc5r03.pdf 6.26.3.3.3 states that with non-CD this would
be a useless fake always starting at track 1, lba 0.
My drives return useful data, though.
MMC-3 states that DVD had no tracks. So maybe this mandatory fake
is a forgotten legacy ?
*/
memcpy(c.opcode, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO));
c.retry = 1;
c.oplen = sizeof(MMC_GET_MSINFO);
c.page = &buf;
c.page->bytes = 0;
c.page->sectors = 0;
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
if (c.error)
return 0;
tdata = c.page->data + 4;
*trackno = tdata[2];
*start = mmc_four_char_to_int(tdata + 4);
return 1;
}
void mmc_read_disc_info(struct burn_drive *d)
{
struct buffer buf;
unsigned char *data;
struct command c;
char msg[160];
/* ts A70131 : had to move mmc_read_toc() to end of function */
int do_read_toc = 0, session_state;
/* ts A61020 */
d->start_lba = d->end_lba = -2000000000;
d->erasable = 0;
d->last_track_no = 1;
/* ts A61202 */
d->toc_entries = 0;
@ -541,20 +929,6 @@ void mmc_read_disc_info(struct burn_drive *d)
return;
mmc_get_configuration(d);
if ((d->current_profile != 0 || d->status != BURN_DISC_UNREADY)
&& ! d->current_is_supported_profile) {
if (!d->silent_on_scsi_error) {
sprintf(msg,
"Unsuitable media detected. Profile %4.4Xh %s",
d->current_profile, d->current_profile_text);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011e,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0,0);
}
d->status = BURN_DISC_UNSUITABLE;
return;
}
mmc_function_spy("mmc_read_disc_info");
memcpy(c.opcode, MMC_GET_DISC_INFO, sizeof(MMC_GET_DISC_INFO));
@ -574,10 +948,6 @@ void mmc_read_disc_info(struct burn_drive *d)
data = c.page->data;
d->erasable = !!(data[2] & 16);
/*
fprintf(stderr, "libburn_experimental: data[2]= %d 0x%x\n",
(unsigned) data[2], (unsigned) data[2]);
*/
switch (data[2] & 3) {
case 0:
d->toc_entries = 0;
@ -595,11 +965,33 @@ void mmc_read_disc_info(struct burn_drive *d)
case 1:
d->status = BURN_DISC_APPENDABLE;
case 2:
if (d->current_profile == -1 || d->current_is_cd_profile)
mmc_read_toc(d);
if ((data[2] & 3) == 2) {
d->status = BURN_DISC_FULL;
#ifdef Libburn_support_dvd_r_seQ
/* offers no feature 0021h now but might do if blank */
if (d->current_profile == 0x14) /* DVD-RW */
d->current_is_supported_profile = 1;
#endif
}
do_read_toc = 1;
break;
}
if ((d->current_profile != 0 || d->status != BURN_DISC_UNREADY)
&& ! d->current_is_supported_profile) {
if (!d->silent_on_scsi_error) {
sprintf(msg,
"Unsuitable media detected. Profile %4.4Xh %s",
d->current_profile, d->current_profile_text);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011e,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0,0);
}
d->status = BURN_DISC_UNSUITABLE;
return;
}
/* >>> ts A61217 : Note for future
growisofs performs OPC if (data[0]<<8)|data[1]<=32
which indicates no OPC entries are attached to the
@ -614,6 +1006,23 @@ void mmc_read_disc_info(struct burn_drive *d)
*/
d->bg_format_status = data[7] & 3;
if (d->status == BURN_DISC_BLANK) {
d->last_track_no = 1; /* The "incomplete track" */
d->complete_sessions = 0;
} else {
/* ts A70131 : number of non-empty sessions */
d->complete_sessions = (data[9] << 8) | data[4];
session_state = (data[2] >> 2) & 3;
/* mmc5r03c.pdf 6.22.3.1.3 State of Last Session: 3=complete */
if (session_state != 3 && d->complete_sessions >= 1)
d->complete_sessions--;
/* ts A70129 : mmc5r03c.pdf 6.22.3.1.7
This includes the "incomplete track" if the disk is
appendable. I.e number of complete tracks + 1. */
d->last_track_no = (data[11] << 8) | data[6];
}
/* Preliminarily declare blank:
ts A61219 : DVD+RW (is not bg_format_status==0 "blank")
ts A61229 : same for DVD-RW Restricted overwrite
@ -622,6 +1031,9 @@ void mmc_read_disc_info(struct burn_drive *d)
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12)
d->status = BURN_DISC_BLANK;
if (do_read_toc)
mmc_read_toc(d);
}
void mmc_read_atip(struct burn_drive *d)
@ -1067,13 +1479,17 @@ static char *mmc_obtain_profile_name(int profile_number)
void mmc_get_configuration(struct burn_drive *d)
{
struct buffer buf;
int len, cp;
int len, cp, descr_len = 0, feature_code, prf_number, only_current = 1;
unsigned char *descr, *prf, *up_to, *prf_end;
struct command c;
d->current_profile = 0;
d->current_profile_text[0] = 0;
d->current_is_cd_profile = 0;
d->current_is_supported_profile = 0;
d->current_has_feat21h = 0;
d->current_feat21h_link_size = -1;
d->current_feat2fh_byte4 = -1;
mmc_function_spy("mmc_get_configuration");
memcpy(c.opcode, MMC_GET_CONFIGURATION, sizeof(MMC_GET_CONFIGURATION));
@ -1088,9 +1504,9 @@ void mmc_get_configuration(struct burn_drive *d)
if (c.error)
return;
len = (c.page->data[0] << 24)
+ (c.page->data[1] << 16)
+ (c.page->data[2] << 8)
+ c.page->data[3];
| (c.page->data[1] << 16)
| (c.page->data[2] << 8)
| c.page->data[3];
if (len<8)
return;
@ -1112,11 +1528,134 @@ void mmc_get_configuration(struct burn_drive *d)
if (cp == 0x12)
d->current_is_supported_profile = 1;
#endif
#ifdef Libburn_support_dvd_r_seQ
if (cp == 0x11 || cp == 0x14)
d->current_is_supported_profile = 1;
#endif
/* >>> see mmc5r03c.pdf 5.2
Interpret list of profile and feature descriptors.
/* Enable this to get loud and repeated reports about the feature set :
#define Libburn_print_feature_descriptorS 1
*/
/* ts A70127 : Interpret list of profile and feature descriptors.
see mmc5r03c.pdf 5.2
>>> Ouch: What to do if list is larger than buffer size.
Specs state that the call has to be repeated.
*/
up_to = c.page->data + (len < BUFFER_SIZE ? len : BUFFER_SIZE);
#ifdef Libburn_print_feature_descriptorS
fprintf(stderr,
"-----------------------------------------------------------------\n");
fprintf(stderr,
"LIBBURN_EXPERIMENTAL : feature list length = %d , shown = %d\n",
len, up_to - c.page->data);
#endif /* Libburn_print_feature_descriptorS */
for (descr = c.page->data + 8; descr + 3 < up_to; descr += descr_len) {
descr_len = 4 + descr[3];
feature_code = (descr[0] << 8) | descr[1];
if (only_current && !(descr[2] & 1))
continue;
#ifdef Libburn_print_feature_descriptorS
fprintf(stderr,
"LIBBURN_EXPERIMENTAL : %s feature %4.4Xh\n",
descr[2] & 1 ? "+" : "-",
feature_code);
#endif /* Libburn_print_feature_descriptorS */
if (feature_code == 0x0) {
prf_end = descr + 4 + descr[3];
for (prf = descr + 4; prf + 2 < prf_end; prf += 4) {
if (only_current && !(prf[2] & 1))
continue;
prf_number = (prf[0] << 8) | prf[1];
#ifdef Libburn_print_feature_descriptorS
fprintf(stderr,
"LIBBURN_EXPERIMENTAL : %s profile %4.4Xh \"%s\"\n",
prf[2] & 1 ? "+" : "-",
prf_number,
mmc_obtain_profile_name(prf_number));
#endif /* Libburn_print_feature_descriptorS */
}
} else if (feature_code == 0x21) {
int i;
d->current_has_feat21h = (descr[2] & 1);
for (i = 0; i < descr[7]; i++) {
if (i == 0 || descr[8 + i] == 16)
d->current_feat21h_link_size =
descr[8 + i];
#ifdef Libburn_print_feature_descriptorS
fprintf(stderr,
"LIBBURN_EXPERIMENTAL : + Link Size = %d\n",
descr[8 + i]);
#endif /* Libburn_print_feature_descriptorS */
}
} else if (feature_code == 0x2F) {
if (descr[2] & 1)
d->current_feat2fh_byte4 = descr[4];
#ifdef Libburn_print_feature_descriptorS
fprintf(stderr, "LIBBURN_EXPERIMENTAL : BUF = %d , Test Write = %d , DVD-RW = %d\n",
!!(descr[4] & 64), !!(descr[4] & 4),
!!(descr[4] & 2));
#endif /* Libburn_print_feature_descriptorS */
#ifdef Libburn_print_feature_descriptorS
} else if (feature_code == 0x01) {
int pys_if_std = 0;
char *phys_name = "";
pys_if_std = (descr[4] << 24) | (descr[5] << 16) |
(descr[6] << 8) | descr[9];
if (pys_if_std == 1)
phys_name = "SCSI Family";
else if(pys_if_std == 2)
phys_name = "ATAPI";
else if(pys_if_std == 3 || pys_if_std == 4 ||
pys_if_std == 6)
phys_name = "IEEE 1394 FireWire";
else if(pys_if_std == 7)
phys_name = "Serial ATAPI";
else if(pys_if_std == 7)
phys_name = "USB";
fprintf(stderr,
"LIBBURN_EXPERIMENTAL : Phys. Interface Standard %Xh \"%s\"\n",
pys_if_std, phys_name);
} else if (feature_code == 0x107) {
fprintf(stderr, "LIBBURN_EXPERIMENTAL : CD SPEED = %d , page 2Ah = %d , SET STREAMING = %d\n",
!!(descr[4] & 8), !!(descr[4] & 4),
!!(descr[4] & 2));
} else if (feature_code == 0x108 || feature_code == 0x10c) {
int i, c_limit;
fprintf(stderr, "LIBBURN_EXPERIMENTAL : %s = ",
feature_code == 0x108 ?
"Drive Serial Number" : "Drive Firmware Date");
c_limit = descr[3] - 2 * (feature_code == 0x10c);
for (i = 0; i < c_limit; i++)
if (descr[4 + i] < 0x20 || descr[4 + i] > 0x7e
|| descr[4 + i] == '\\')
fprintf(stderr,"\\%2.2X",descr[4 + i]);
else
fprintf(stderr, "%c", descr[4 + i]);
fprintf(stderr, "\n");
#endif /* Libburn_print_feature_descriptorS */
}
}
}
@ -1210,6 +1749,8 @@ int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
score = 100 * sign;
} else if(type == 0x15) { /* DVD-RW Quick */
score = 50 * sign;
} else if(type == 0x26) { /* DVD+RW */
score = 1 * sign;
} else {
continue;
}
@ -1243,6 +1784,11 @@ void mmc_sync_cache(struct burn_drive *d)
c.oplen = sizeof(MMC_SYNC_CACHE);
c.page = NULL;
c.dir = NO_TRANSFER;
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
"syncing cache", 0, 0);
d->issue_command(d, &c);
}
@ -1412,7 +1958,7 @@ selected_not_suitable:;
if (d->format_descr_type == 2) /* formatted */
return 1;
if (d->format_descr_type == 3){/*intermediate*/
d->dvd_minus_rw_incomplete = 1;
d->needs_close_session = 1;
return 1;
}
/* does trying make sense at all ? */
@ -1510,7 +2056,7 @@ unsuitable_media:;
}
return 0;
} else if ((!c.error) && (format_type == 0x13 || format_type == 0x15))
d->dvd_minus_rw_incomplete = 1;
d->needs_close_session = 1;
if (return_immediately)
return 1;
usleep(1000000); /* there seems to be a little race condition */
@ -1651,8 +2197,10 @@ int mmc_setup_drive(struct burn_drive *d)
d->perform_opc = mmc_perform_opc;
d->set_speed = mmc_set_speed;
d->send_cue_sheet = mmc_send_cue_sheet;
d->reserve_track = mmc_reserve_track;
d->sync_cache = mmc_sync_cache;
d->get_nwa = mmc_get_nwa;
d->read_multi_session_c1 = mmc_read_multi_session_c1;
d->close_disc = mmc_close_disc;
d->close_session = mmc_close_session;
d->close_track_session = mmc_close;
@ -1664,15 +2212,20 @@ int mmc_setup_drive(struct burn_drive *d)
d->start_lba = -2000000000;
d->end_lba = -2000000000;
/* ts A61201 */
/* ts A61201 - A70128 */
d->erasable = 0;
d->current_profile = -1;
d->current_profile_text[0] = 0;
d->current_is_cd_profile = 0;
d->current_is_supported_profile = 0;
d->dvd_minus_rw_incomplete = 0;
d->current_has_feat21h = 0;
d->current_feat21h_link_size = -1;
d->current_feat2fh_byte4 = -1;
d->needs_close_session = 0;
d->bg_format_status = -1;
d->num_format_descr = 0;
d->complete_sessions = 0;
d->last_track_no = 1;
return 1;
}
@ -1690,8 +2243,8 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
pd[0] = 5;
pd[1] = d->mdata->write_page_length;
/* ts A61229 */
if (d->current_profile == 0x13) { /* DVD-RW restricted overwrite */
if (d->current_profile == 0x13) {
/* A61229 : DVD-RW restricted overwrite */
/* learned from transport.hxx : page05_setup()
and mmc3r10g.pdf table 347 */
/* BUFE (burnproof), no LS_V (i.e. default Link Size, i hope),
@ -1703,8 +2256,58 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
pd[4] = 8;
/* Link size dummy */
pd[5] = 0;
} else if ((d->current_profile == 0x14 || d->current_profile == 0x11)
&& o->write_type == BURN_WRITE_SAO) {
/* ts A70205 : DVD-R[W} : Disc-at-once, DAO */
/* Learned from dvd+rw-tools and mmc5r03c.pdf .
See doc/cookbook.txt for more detailed references. */
/* BUFE , LS_V = 0, Test Write, Write Type = 2 SAO (DAO) */
pd[2] = ((!!o->underrun_proof) << 6)
| ((!!o->simulate) << 4)
| 2;
/* No multi-session , FP = 0 , Track Mode = 5 */
pd[3] = 5;
/* Data Block Type = 8 */
pd[4] = 8;
} else if (d->current_profile == 0x14 || d->current_profile == 0x11) {
/* ts A70128 : DVD-R[W] Incremental Streaming */
/* Learned from transport.hxx : page05_setup()
and mmc5r03c.pdf 7.5, 4.2.3.4 Table 17
and spc3r23.pdf 6.8, 7.4.3 */
/* BUFE , LS_V = 1, Test Write,
Write Type = 0 Packet/Incremental */
pd[2] = ((!!o->underrun_proof) << 6)
| (1 << 5)
| ((!!o->simulate) << 4);
/* Multi-session , FP = 1 , Track Mode = 5 */
pd[3] = ((3 * !!o->multi) << 6) | (1 << 5) | 5;
/* Data Block Type = 8 */
pd[4] = 8;
/* Link Size */
if (d->current_feat21h_link_size >= 0)
pd[5] = d->current_feat21h_link_size;
else
pd[5] = 16;
if (d->current_feat21h_link_size != 16) {
char msg[80];
sprintf(msg,
"Feature 21h Link Size = %d (expected 16)\n",
d->current_feat21h_link_size);
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msg, 0, 0);
}
/* Packet Size */
pd[13] = 16;
} else {
/* Traditional setup for CD */
pd[2] = ((!!o->underrun_proof) << 6)
| ((!!o->simulate) << 4)
| (o->write_type & 0x0f);

View File

@ -21,6 +21,10 @@ struct burn_source *burn_null_source_new(void)
src->read_sub = NULL;
src->get_size = 0;
/* ts A70126 */
src->set_size = NULL;
src->free_data = NULL;
src->data = NULL;
return src;

View File

@ -1,5 +1,6 @@
#include "libburn.h"
#include "options.h"
#include "drive.h"
#include "transport.h"
/* ts A61007 */
@ -170,6 +171,96 @@ void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value)
}
/* ts A70207 API */
enum burn_write_types burn_write_opts_auto_write_type(
struct burn_write_opts *opts, struct burn_disc *disc,
char reasons[1024], int flag)
{
struct burn_multi_caps *caps = NULL;
struct burn_drive *d = opts->drive;
struct burn_disc_mode_demands demands;
int ret;
char *reason_pt;
reasons[0] = 0;
ret = burn_disc_get_write_mode_demands(disc, &demands, 0);
if (ret <= 0) {
strcat(reasons, "cannot recognize job demands, ");
return BURN_WRITE_NONE;
}
if (demands.exotic_track && !d->current_is_cd_profile) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020123,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"DVD Media are unsuitable for desired track type",
0, 0);
if (demands.audio)
strcat(reasons, "audio track prohibited by non-CD, ");
else
strcat(reasons, "exotic track prohibited by non-CD, ");
return BURN_WRITE_NONE;
}
ret = burn_disc_get_multi_caps(d, BURN_WRITE_SAO, &caps, 0);
if (ret < 0) {
no_caps:;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002012a,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Cannot inquire write mode capabilities",
0, 0);
strcat(reasons, "cannot inquire write mode capabilities, ");
return BURN_WRITE_NONE;
} if (ret > 0) {
reason_pt = reasons + strlen(reasons);
strcat(reasons, "SAO: ");
if ((opts->multi || demands.multi_session) &&
!caps->multi_session)
strcat(reasons, "multi session capability lacking, ");
if (demands.multi_track && !caps->multi_track)
strcat(reasons, "multi track capability lacking, ");
if (demands.unknown_track_size)
strcat(reasons, "track size unpredictable, ");
if (demands.mixed_mode)
strcat(reasons, "tracks of different modes mixed, ");
if (strcmp(reason_pt, "SAO: ") != 0)
goto no_sao;
burn_write_opts_set_write_type(opts,
BURN_WRITE_SAO, BURN_BLOCK_SAO);
return BURN_WRITE_SAO;
} else
strcat(reasons, "SAO: no SAO offered by drive and media, ");
no_sao:;
burn_disc_free_multi_caps(&caps);
strcat(reasons, "\n");
reason_pt = reasons + strlen(reasons);
strcat(reasons, "TAO: ");
ret = burn_disc_get_multi_caps(d, BURN_WRITE_TAO, &caps, 0);
if (ret < 0)
goto no_caps;
if (ret == 0) {
strcat(reasons, "no TAO offered by drive and media, ");
no_write_mode:;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002012b,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive offers no suitable write mode with this job",
0, 0);
return BURN_WRITE_NONE;
}
if ((opts->multi || demands.multi_session) && !caps->multi_session)
strcat(reasons, "multi session capability lacking, ");
if (demands.multi_track && !caps->multi_track)
strcat(reasons, "multi track capability lacking, ");
if (strcmp(reason_pt, "TAO: ") != 0)
goto no_write_mode;
/* ( TAO data/audio block size will be handled automatically ) */
burn_write_opts_set_write_type(opts,
BURN_WRITE_TAO, BURN_BLOCK_MODE1);
return BURN_WRITE_TAO;
}
void burn_read_opts_set_raw(struct burn_read_opts *opts, int raw)
{
opts->raw = raw;

View File

@ -7,10 +7,6 @@
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
#ifndef BURN_OS_H_INCLUDED
#define BURN_OS_H_INCLUDED 1
/** List of all signals which shall be caught by signal handlers and trigger
a graceful abort of libburn. (See man 7 signal.)
*/
@ -52,14 +48,9 @@ SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
which are now local in sg_enumerate() . So that sg_give_next_adr()
can work in BSD and sg_enumerate() can use it.
*/
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
struct burn_drive_enumeration_state { \
union ccb ccb; \
int bufsize, fd; \
unsigned int i; \
int skip_device; \
}; \
typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
struct burn_drive_enumeration_state; \
typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
/* The list of operating system dependent elements in struct burn_drive.
@ -68,6 +59,3 @@ typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
struct cam_device* cam;
#endif /* ! BURN_OS_H_INCLUDED */

View File

@ -1,19 +1,5 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Revives old enumerate_common(). New version delegates much work
to methods in drive, mmc, spc, and sbc .
*/
#define Scsi_freebsd_make_own_enumeratE 1
/* Revives old scsi_enumerate_drives(). New version delegates most work to
sg_give_next_adr().
*/
#define Scsi_freebsd_old_scsi_enumeratE 1
#include <assert.h>
#include <errno.h>
#include <unistd.h>
@ -45,6 +31,13 @@
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
struct burn_drive_enumeration_state {
int fd;
union ccb ccb;
unsigned int i;
int skip_device;
};
static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no);
@ -57,33 +50,20 @@ int burn_drive_is_banned(char *device_address);
int mmc_function_spy(char * text);
#ifdef Scsi_freebsd_old_scsi_enumeratE
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
return (0);
}
int sg_is_enumerable_adr(char* adr)
{
return (0);
}
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
return (0);
}
#else /* Scsi_freebsd_old_scsi_enumeratE */
/* ts A61021 : Moved most code from scsi_enumerate_drives under
sg_give_next_adr() */
/* Some helper functions for scsi_give_next_adr() */
static int sg_init_enumerator(burn_drive_enumerator_t *idx)
static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
{
struct burn_drive_enumeration_state *idx;
int bufsize;
idx = malloc(sizeof(*idx));
if (idx == NULL) {
warnx("can't malloc memory for enumerator");
return -1;
}
idx->skip_device = 0;
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
@ -98,12 +78,13 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx)
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
idx->bufsize = sizeof(struct dev_match_result) * 100;
idx->ccb.cdm.match_buf_len = idx->bufsize;
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(idx->bufsize);
bufsize = sizeof(struct dev_match_result) * 100;
idx->ccb.cdm.match_buf_len = bufsize;
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
if (idx->ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(idx->fd);
free(idx);
return -1;
}
idx->ccb.cdm.num_matches = 0;
@ -116,12 +97,28 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx)
idx->ccb.cdm.num_patterns = 0;
idx->ccb.cdm.pattern_buf_len = 0;
*idx_ = idx;
return 1;
}
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
static void sg_destroy_enumerator(burn_drive_enumerator_t *idx_)
{
struct burn_drive_enumeration_state *idx = *idx_;
if(idx->fd != -1)
close(idx->fd);
free(idx->ccb.cdm.matches);
free(idx);
*idx_ = NULL;
}
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
{
struct burn_drive_enumeration_state *idx = *idx_;
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
@ -152,95 +149,94 @@ static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
@return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx,
int sg_give_next_adr(burn_drive_enumerator_t *idx_,
char adr[], int adr_size, int initialize)
{
struct burn_drive_enumeration_state *idx;
int ret;
if (initialize == 1) {
ret = sg_init_enumerator(idx);
ret = sg_init_enumerator(idx_);
if (ret<=0)
return ret;
} else if (initialize == -1) {
if(idx->fd != -1)
close(idx->fd);
idx->fd = -1;
sg_destroy_enumerator(idx_);
return 0;
}
idx = *idx_;
try_item:; /* This spaghetti loop keeps the number of tabs small */
do {
if (idx->i >= idx->ccb.cdm.num_matches) {
ret = sg_next_enumeration_buffer(idx_);
if (ret<=0)
return -1;
idx->i = 0;
} else
(idx->i)++;
/* Loop content from old scsi_enumerate_drives() */
while (idx->i < idx->ccb.cdm.num_matches) {
switch (idx->ccb.cdm.matches[idx->i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
while (idx->i >= idx->ccb.cdm.num_matches) {
ret = sg_next_enumeration_buffer(idx);
if (ret<=0)
return -1;
if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
return 0;
idx->i = 0;
}
result = &(idx->ccb.cdm.matches[idx->i].result.device_result);
if (result->flags & DEV_RESULT_UNCONFIGURED)
idx->skip_device = 1;
else
idx->skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
switch (idx->ccb.cdm.matches[idx->i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
ret = snprintf(adr, adr_size, "/dev/%s%d",
result->periph_name, result->unit_number);
if(ret >= adr_size)
return -1;
result = &(idx->ccb.cdm.matches[i].result.device_result);
if (result->flags & DEV_RESULT_UNCONFIGURED)
idx->skip_device = 1;
else
idx->skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
/* Found next enumerable address */
return 1;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d",
result->periph_name, result->unit_number);
if(adr_size <= strlen(buf)
return -1;
strcpy(adr, buf);
}
default:
/* printf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
}
} while ((idx->ccb.ccb_h.status == CAM_REQ_CMP)
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE));
/* Found next enumerable address */
return 1;
}
default:
/* printf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
goto try_item; /* Regular function exit is return 1 above */
return 0;
}
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1;
int ret;
char buf[64];
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
if (ret <= 0)
break;
break;
if (strcmp(adr, buf) == 0) {
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
sg_destroy_enumerator(&idx);
return 1;
}
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
sg_destroy_enumerator(&idx);
return (0);
}
@ -252,32 +248,32 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
burn_drive_enumerator_t idx;
int initialize = 1;
int ret;
char buf[64];
struct periph_match_result* result;
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
if (ret <= 0)
break;
if (strcmp(adr, buf) != 0)
continue;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
*bus_no = result->path_id;
*host_no = result->path_id;
*channel_no = 0;
*target_no = result->target_id
*lun_no = result->target_lun;
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
break;
if (strcmp(path, buf) == 0) {
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
*bus_no = result->path_id;
*host_no = result->path_id;
*channel_no = 0;
*target_no = result->target_id;
*lun_no = result->target_lun;
sg_destroy_enumerator(&idx);
return 1;
}
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
sg_destroy_enumerator(&idx);
return (0);
}
#endif /* ! Scsi_freebsd_old_scsi_enumeratE */
int sg_close_drive(struct burn_drive * d)
{
@ -295,125 +291,28 @@ int sg_drive_is_open(struct burn_drive * d)
int scsi_enumerate_drives(void)
{
#ifdef Scsi_freebsd_old_scsi_enumeratE
union ccb ccb;
int bufsize, fd;
unsigned int i;
int skip_device = 0;
if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
return;
}
bzero(&ccb, sizeof(union ccb));
ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
ccb.ccb_h.func_code = XPT_DEV_MATCH;
bufsize = sizeof(struct dev_match_result) * 100;
ccb.cdm.match_buf_len = bufsize;
ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
if (ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(fd);
return;
}
ccb.cdm.num_matches = 0;
/*
* We fetch all nodes, since we display most of them in the default
* case, and all in the verbose case.
*/
ccb.cdm.num_patterns = 0;
ccb.cdm.pattern_buf_len = 0;
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
*/
do {
if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
warn("error sending CAMIOCOMMAND ioctl");
break;
}
if ((ccb.ccb_h.status != CAM_REQ_CMP)
|| ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
&& (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
warnx("got CAM error %#x, CDM error %d\n",
ccb.ccb_h.status, ccb.cdm.status);
break;
}
for (i = 0; i < ccb.cdm.num_matches; i++) {
switch (ccb.cdm.matches[i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &ccb.cdm.matches[i].result.device_result;
if (result->flags & DEV_RESULT_UNCONFIGURED)
skip_device = 1;
else
skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
result = &ccb.cdm.matches[i].result.periph_result;
if (skip_device || strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d", result->periph_name, result->unit_number);
/* ts A51221 */
if (burn_drive_is_banned(buf))
break;
enumerate_common(buf, result->path_id, result->path_id, 0,
result->target_id, result->target_lun);
break;
}
default:
fprintf(stdout, "unknown match type\n");
break;
}
}
} while ((ccb.ccb_h.status == CAM_REQ_CMP)
&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
close(fd);
#else /* Scsi_freebsd_old_scsi_enumeratE */
burn_drive_enumerator_t idx;
int initialize = 1;
int ret;
char buf[64];
struct periph_match_result* result;
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
if (ret <= 0)
break;
break;
if (burn_drive_is_banned(buf))
continue;
enumerate_common(buf, idx.result->path_id, idx.result->path_id,
0, idx.result->target_id,
idx.result->target_lun);
continue;
result = &idx->ccb.cdm.matches[idx->i].result.periph_result;
enumerate_common(buf, result->path_id, result->path_id,
0, result->target_id,
result->target_lun);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
#endif /* ! Scsi_freebsd_old_scsi_enumeratE */
sg_destroy_enumerator(&idx);
return 1;
}
@ -551,7 +450,10 @@ int sg_grab(struct burn_drive *d)
mmc_function_spy("sg_grab");
assert(d->cam == NULL);
if (burn_drive_is_open(d)) {
d->released = 0;
return 1;
}
cam = cam_open_device(d->devname, O_RDWR);
if (cam == NULL) {
@ -591,6 +493,7 @@ int sg_release(struct burn_drive *d)
mmc_function_spy("sg_release ----------- closing.");
sg_close_drive(d);
d->released = 1;
return 0;
}

View File

@ -317,7 +317,8 @@ void burn_track_clear_isrc(struct burn_track *t)
int burn_track_get_sectors(struct burn_track *t)
{
int size;
/* ts A70125 : was int */
off_t size;
int sectors, seclen;
seclen = burn_sector_length(t->mode);
@ -329,6 +330,22 @@ int burn_track_get_sectors(struct burn_track *t)
return sectors;
}
/* ts A70125 */
int burn_track_set_sectors(struct burn_track *t, int sectors)
{
off_t size, seclen;
int ret;
seclen = burn_sector_length(t->mode);
size = seclen * (off_t) sectors - (off_t) t->offset - (off_t) t->tail;
if (size < 0)
return 0;
ret = t->source->set_size(t->source, size);
return ret;
}
/* ts A61031 */
int burn_track_is_open_ended(struct burn_track *t)
{

View File

@ -88,5 +88,8 @@ int burn_track_get_shortage(struct burn_track *t);
int burn_track_is_open_ended(struct burn_track *t);
int burn_track_is_data_done(struct burn_track *t);
/* ts A70125 */
int burn_track_set_sectors(struct burn_track *t, int sectors);
#endif /* BURN__STRUCTURE_H */

View File

@ -152,11 +152,29 @@ struct burn_drive
int current_is_cd_profile;
int current_is_supported_profile;
/* ts A70128 : MMC-to-MMC feature info from 46h for DVD-RW.
Quite internal. Regard as opaque :)
*/
/* 1 = incremental recording available, 0 = not available */
int current_has_feat21h;
/* Link Size item number 0 from feature 0021h descriptor */
int current_feat21h_link_size;
/* Flags from feature 002Fh feature descriptor mmc5r03c.pdf 5.3.25 :
bit1= DVD-RW supported
bit2= Test Write available
bit3= DVD-R DL supported
bit6= Buffer Under-run Free recording available (page 05h BUFE)
Value -1 indicates that no 002Fh was current in the features list.
*/
int current_feat2fh_byte4;
/* ts A70114 : wether a DVD-RW media holds an incomplete session
(which could need closing after write) */
int dvd_minus_rw_incomplete;
int needs_close_session;
/* ts A61218 from 46h GET CONFIGURATION */
/* ts A61218 from 51h READ DISC INFORMATION */
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
/* ts A70108 from 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24 */
@ -181,6 +199,15 @@ struct burn_drive
int rlba; /* relative lba in section */
int start_lba;
int end_lba;
/* ts A70131 : from 51h READ DISC INFORMATION Number of Sessions (-1)*/
int complete_sessions;
/* ts A70129 :
from 51h READ DISC INFORMATION Last Track Number in Last Session */
int last_track_no;
int toc_temp;
struct burn_disc *disc; /* disc structure */
int block_types[4];
@ -224,10 +251,19 @@ struct burn_drive
void (*send_write_parameters) (struct burn_drive *,
const struct burn_write_opts *);
void (*send_cue_sheet) (struct burn_drive *, struct cue_sheet *);
/* ts A70205 : Announce size of a DVD-R[W] DAO session. */
int (*reserve_track) (struct burn_drive *d, off_t size);
void (*sync_cache) (struct burn_drive *);
int (*get_erase_progress) (struct burn_drive *);
int (*get_nwa) (struct burn_drive *, int trackno, int *lba, int *nwa);
/* ts A70131 : obtain (possibly fake) TOC number and start lba of
first track in last complete session */
int (*read_multi_session_c1)(struct burn_drive *d,
int *trackno, int *start);
/* ts A61009 : removed d in favor of o->drive */
/* void (*close_disc) (struct burn_drive * d,
struct burn_write_opts * o);

View File

@ -195,7 +195,10 @@ int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
/* MMC-1 mentions track number 0xFF for "the incomplete track",
MMC-3 does not. I tried both. 0xFF was in effect when other
bugs finally gave up and made way for readable tracks. */
d->close_track_session(o->drive, 0, 0xff); /* tnum+1); */
/* ts A70129
Probably the right value for appendables is d->last_track_no
*/
d->close_track_session(o->drive, 0, 0xff);
/* ts A61102 */
d->busy = BURN_DRIVE_WRITING;
@ -298,7 +301,7 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
struct burn_session *session,
int nwa)
{
int i, m, s, f, form, pform, runtime = -150, ret;
int i, m, s, f, form, pform, runtime = -150, ret, track_length;
unsigned char ctladr;
struct burn_drive *d;
struct burn_toc_entry *e;
@ -386,10 +389,22 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
e[2].control = e[1].control;
e[2].adr = 1;
/* ts A70121 : The pause before the first track is not a Pre-gap.
To count it as part 2 of a Pre-gap is a dirty hack. It also seems
to have caused confusion in dealing with part 1 of an eventual
real Pre-gap. mmc5r03c.pdf 6.33.3.2, 6.33.3.18 .
*/
tar[0]->pregap2 = 1;
pform = form;
for (i = 0; i < ntr; i++) {
type_to_form(tar[i]->mode, &ctladr, &form);
/* ts A70121 : This seems to be thw wrong test. Correct would
be to compare tar[]->mode or bit2 of ctladr.
*/
if (pform != form) {
ret = add_cue(sheet, ctladr | 1, i + 1, 0, form, 0,
@ -405,6 +420,21 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
/ / if (!(form & BURN_AUDIO))
/ / tar[i]->pregap1 = 1;
*/
/* ts A70121 : it is unclear why (form & BURN_AUDIO) should prevent pregap1.
I believe, correct would be:
runtime += 75;
tar[i]->pregap1 = 1;
The test for pform != form is wrong anyway.
Next one has to care for Post-gap: table 555 in mmc5r03c.pdf does not
show any although 6.33.3.19 would prescribe some.
Nobody seems to have ever tested this situation, up to now.
It is banned for now in burn_disc_write().
Warning have been placed in libburn.h .
*/
tar[i]->pregap2 = 1;
}
/* XXX HERE IS WHERE WE DO INDICES IN THE CUE SHEET */
@ -424,7 +454,20 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
if (ret <= 0)
goto failed;
runtime += burn_track_get_sectors(tar[i]);
/* ts A70125 :
Still not understanding the sense behind linking tracks,
i decided to at least enforce the MMC specs' minimum
track length.
*/
track_length = burn_track_get_sectors(tar[i]);
if (track_length < 300) {
track_length = 300;
if (!tar[i]->pad)
tar[i]->pad = 1;
burn_track_set_sectors(tar[i], track_length);
}
runtime += track_length;
/* if we're padding, we'll clear any current shortage.
if we're not, we'll slip toc entries by a sector every time our
shortage is more than a sector
@ -626,12 +669,27 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
d->rlba += 150;
if (t->pregap1) {
struct burn_track *pt = s->track[tnum - 1];
struct burn_track *pt;
/* ts A70121 : Removed pseudo suicidal initializer
= s->track[tnum - 1];
*/
if (tnum == 0) {
/* ts A70121 : This is not possible because
track 1 cannot have a pregap at all.
MMC-5 6.33.3.2 precribes a mandatory pause
prior to any track 1. Pre-gap is prescribed
for mode changes like audio-to-data.
To set burn_track.pregap1 for track 1 is
kindof a dirty hack.
*/
printf("first track should not have a pregap1\n");
pt = t;
}
} else
pt = s->track[tnum - 1]; /* ts A70121 */
for (i = 0; i < 75; i++)
if (!sector_pregap(o, t->entry->point,
pt->entry->control, pt->mode))
@ -810,7 +868,71 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
}
/* ts A61218 */
/* ts A70129 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */
int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
struct burn_session *s, int tnum)
{
struct burn_drive *d = o->drive;
char msg[160];
int ret, lba, nwa;
off_t size;
d->send_write_parameters(d, o);
ret = d->get_nwa(d, -1, &lba, &nwa);
sprintf(msg,
"DVD pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d",
tnum+1, nwa, ret, d->nwa);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0);
if (nwa > d->nwa)
d->nwa = nwa;
if (o->write_type == BURN_WRITE_SAO) { /* DAO */
/* Round track size up to 32 KiB and reserve track */
size = ((off_t) burn_track_get_sectors(s->track[tnum]))
* (off_t) 2048;
size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff);
ret = d->reserve_track(d, size);
if (ret <= 0) {
sprintf(msg, "Cannot reserve track of %.f bytes",
(double) size);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020138,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0,0);
return 0;
}
}
return 1;
}
/* ts A70129 */
int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o,
struct burn_session *s, int tnum)
{
struct burn_drive *d = o->drive;
char msg[80];
/* only with Incremental writing */
if (o->write_type != BURN_WRITE_TAO)
return 2;
sprintf(msg, "Closing track %2.2d (absolute track number %d)",
tnum + 1, d->last_track_no);
libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg,0,0);
d->busy = BURN_DRIVE_CLOSING_SESSION;
/* Ignoring tnum here and hoping that d->last_track_no is correct */
d->close_track_session(d, 0, d->last_track_no); /* CLOSE TRACK, 001b */
d->busy = BURN_DRIVE_WRITING;
d->last_track_no++;
return 1;
}
/* ts A61218 - A70129 */
int burn_dvd_write_track(struct burn_write_opts *o,
struct burn_session *s, int tnum)
{
@ -818,12 +940,17 @@ int burn_dvd_write_track(struct burn_write_opts *o,
struct burn_drive *d = o->drive;
struct buffer *out = d->buffer;
int sectors;
int i, open_ended = 0, ret= 0;
int i, open_ended = 0, ret= 0, is_flushed = 0;
sectors = burn_track_get_sectors(t);
open_ended = burn_track_is_open_ended(t);
/* >>> any type specific track preparations */;
if (d->current_profile == 0x11 || d->current_profile == 0x14) {
/* DVD-R, DVD-RW Sequential */
ret = burn_disc_open_track_dvd_minus_r(o, s, tnum);
if (ret <= 0)
goto ex;
}
burn_disc_init_track_status(o, s, tnum, sectors);
for (i = 0; open_ended || i < sectors; i++) {
@ -846,7 +973,7 @@ int burn_dvd_write_track(struct burn_write_opts *o,
d->progress.sector++;
}
/* Pad up buffer to next full 32 kB */
/* Pad up buffer to next full o->obs (usually 32 kB) */
if (o->obs_pad && out->bytes > 0 && out->bytes < o->obs) {
memset(out->data + out->bytes, 0, o->obs - out->bytes);
out->sectors += (o->obs - out->bytes) / 2048;
@ -855,14 +982,19 @@ int burn_dvd_write_track(struct burn_write_opts *o,
ret = burn_write_flush(o, t);
if (ret <= 0)
goto ex;
is_flushed = 1;
/* >>> any other normal track finalizing */;
/* Eventually finalize track */
if (d->current_profile == 0x11 || d->current_profile == 0x14) {
/* DVD-R, DVD-RW Sequential */
ret = burn_disc_close_track_dvd_minus_r(o, s, tnum);
if (ret != 2)
goto ex;
}
ret = 1;
ex:;
if (ret<=0) {
if (!is_flushed)
d->sync_cache(d); /* burn_write_flush() was not called */
}
return ret;
}
@ -906,6 +1038,27 @@ int burn_disc_close_session_dvd_minus_rw(struct burn_write_opts *o,
}
/* ts A70129 : for profile 0x11 DVD-R and 0x14 DVD-RW Sequential */
int burn_disc_close_session_dvd_minus_r(struct burn_write_opts *o,
struct burn_session *s)
{
struct burn_drive *d = o->drive;
/* only for Incremental writing */
if (o->write_type != BURN_WRITE_TAO)
return 2;
libdax_msgs_submit(libdax_messenger, o->drive->global_index,0x00020119,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Closing session", 0, 0);
d->busy = BURN_DRIVE_CLOSING_SESSION;
d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
d->busy = BURN_DRIVE_WRITING;
return 1;
}
/* ts A61218 */
int burn_dvd_write_session(struct burn_write_opts *o,
struct burn_session *s)
@ -913,26 +1066,35 @@ int burn_dvd_write_session(struct burn_write_opts *o,
int i,ret;
struct burn_drive *d = o->drive;
/* >>> open_session ? */
for (i = 0; i < s->tracks; i++) {
ret = burn_dvd_write_track(o, s, i);
if (ret <= 0)
break;
}
if (d->current_profile == 0x1a) {
/* DVD+RW */
ret = burn_disc_close_session_dvd_plus_rw(o, s);
if ((d->current_profile == 0x11 || d->current_profile == 0x14)) {
/* DVD-R , DVD-RW Sequential */
ret = burn_disc_close_session_dvd_minus_r(o, s);
if (ret <= 0)
return 0;
} else if (d->current_profile == 0x12) {
/* DVD-RAM */
/* ??? any finalization needed ? */;
} else if (d->current_profile == 0x13) {
/* DVD-RW restricted overwrite */
if (d->dvd_minus_rw_incomplete) {
if (d->needs_close_session) {
ret = burn_disc_close_session_dvd_minus_rw(o, s);
if (ret <= 0)
return 0;
}
} else if (d->current_profile == 0x12) {
/* DVD-RAM */
/* ??? any finalization needed ? */;
} else if (d->current_profile == 0x1a) {
/* DVD+RW */
if (d->needs_close_session) {
ret = burn_disc_close_session_dvd_plus_rw(o, s);
if (ret <= 0)
return 0;
}
}
return 1;
}
@ -953,6 +1115,7 @@ int burn_disc_setup_dvd_plus_rw(struct burn_write_opts *o,
if (ret <= 0)
return 0;
d->busy = BURN_DRIVE_WRITING;
d->needs_close_session = 1;
}
d->nwa = 0;
if (o->start_byte >= 0) {
@ -1009,7 +1172,7 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
5.4.14 finally states that profile 0013h includes feature
002Ch rather than 0026h.
d->send_write_parameters(d, o);
d->send_write_parameters(d, o);
*/
d->busy = BURN_DRIVE_FORMATTING;
@ -1039,14 +1202,28 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
}
/* ts A61218 */
/* ts A70129 : for DVD-R[W] Sequential Recoding */
int burn_disc_setup_dvd_minus_r(struct burn_write_opts *o,
struct burn_disc *disc)
{
struct burn_drive *d = o->drive;
/* most setup is in burn_disc_setup_track_dvd_minus_r() */;
d->nwa = 0;
return 1;
}
/* ts A61218 - A70129 */
int burn_dvd_write_sync(struct burn_write_opts *o,
struct burn_disc *disc)
{
int i, ret, sx, tx, mode, exotic_track = 0;
int i, ret, sx, tx, mode, exotic_track = 0, dao_is_ok;
struct burn_drive *d = o->drive;
char msg[160];
d->needs_close_session = 0;
for (sx = 0; sx < disc->sessions; sx++)
for (tx = 0 ; tx < disc->session[sx]->tracks; tx++) {
mode = disc->session[sx]->track[tx]->mode;
@ -1102,7 +1279,8 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
}
o->obs_pad = 0; /* no filling-up of track's last 32k buffer */
} else if (d->current_profile == 0x13) { /* DVD-RW Rest. Overwrite */
} else if (d->current_profile == 0x13) {
/* DVD-RW Restricted Overwrite */
if (o->start_byte >= 0 && (o->start_byte % 32768)) {
sprintf(msg,
"Write start address not properly aligned to 32K");
@ -1123,9 +1301,71 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
goto early_failure;
}
/* ??? is this necessary ? */
/* _Rigid_ Restricted Overwrite demands this */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
} else if (d->current_profile == 0x11 || d->current_profile == 0x14) {
/* DVD-R , DVD-RW Sequential */
dao_is_ok =
(disc->sessions == 1 &&
disc->session[0]->tracks == 1 &&
(! burn_track_is_open_ended(
disc->session[0]->track[0])) &&
(!o->multi) && d->status == BURN_DISC_BLANK
);
if (o->write_type == BURN_WRITE_TAO &&
!d->current_has_feat21h) {
if (dao_is_ok) {
o->write_type = BURN_WRITE_SAO;
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020134,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
"Defaulted TAO to DAO (lack of feature 21h)",
0, 0);
} else {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020135,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot perform TAO (lack of feature 21h), job unsuitable for DAO",
0, 0);
goto early_failure;
}
} else if (o->write_type == BURN_WRITE_SAO && !dao_is_ok) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020136,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"DAO burning is restricted to a single fixed size track and no multi-session",
0,0);
if (d->current_has_feat21h)
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020137,
LIBDAX_MSGS_SEV_HINT,
LIBDAX_MSGS_PRIO_HIGH,
"TAO would be possible and could do the job",
0,0);
goto early_failure;
}
if (o->start_byte >= 0) {
sprintf(msg, "Write start address not supported");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020124,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0,0);
goto early_failure;
}
ret = burn_disc_setup_dvd_minus_r(o, disc);
if (ret <= 0) {
sprintf(msg,
"Write preparation setup failed for DVD-R[W]");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020121,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0,0);
goto early_failure;
}
/* ??? padding needed ??? cowardly doing it for now */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
} else {
sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s",
d->current_profile, d->current_profile_text);

View File

@ -8,8 +8,9 @@
libburner is a minimal demo application for the library libburn as provided
on http://libburnia.pykix.org . It can list the available devices, can
blank a CD-RW, can format a DVD-RW, and can burn to CD-R, CD-RW, DVD+RW,
DVD-RAM or DVD-RW.
blank a CD-RW or DVD-RW, can format a DVD-RW, and can burn to CD-R, CD-RW,
DVD+RW, DVD-RAM or DVD-RW. Not tested: DVD-R. Not supported yet: DVD+R [DL].
It's main purpose, nevertheless, is to show you how to use libburn and also
to serve the libburnia team as reference application. libburner.c does indeed
define the standard way how above three gestures can be implemented and
@ -261,13 +262,15 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
{
enum burn_disc_status disc_state;
struct burn_progress p;
int percent = 1;
double percent = 1.0;
disc_state = burn_disc_get_status(drive);
printf(
"Drive media status: %d (see libburn/libburn.h BURN_DISC_*)\n",
disc_state);
if (disc_state == BURN_DISC_BLANK) {
if (current_profile == 0x13) {
; /* formatted DVD-RW will get blanked to sequential state */
} else if (disc_state == BURN_DISC_BLANK) {
fprintf(stderr,
"IDLE: Blank media detected. Will leave it untouched\n");
return 2;
@ -295,7 +298,7 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
percent = 1.0 + ((double) p.sector+1.0)
/ ((double) p.sectors) * 98.0;
printf("Blanking ( %d%% done )\n", percent);
printf("Blanking ( %.1f%% done )\n", percent);
sleep(1);
}
printf("Done\n");
@ -311,7 +314,7 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
int libburner_format_row(struct burn_drive *drive)
{
struct burn_progress p;
int percent = 1;
double percent = 1.0;
if (current_profile == 0x13) {
fprintf(stderr, "IDLE: DVD-RW media is already formatted\n");
@ -328,7 +331,7 @@ int libburner_format_row(struct burn_drive *drive)
if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
percent = 1.0 + ((double) p.sector+1.0)
/ ((double) p.sectors) * 98.0;
printf("Formatting ( %d%% done )\n", percent);
printf("Formatting ( %.1f%% done )\n", percent);
sleep(1);
}
burn_disc_get_profile(drive_list[0].drive, &current_profile,
@ -351,6 +354,9 @@ int libburner_format_row(struct burn_drive *drive)
In case of external signals expect abort handling of an ongoing burn to
last up to a minute. Wait the normal burning timespan before any kill -9.
For simplicity, this function allows memory leaks in case of failure.
In apps which do not abort immediately, one should clean up better.
*/
int libburner_payload(struct burn_drive *drive,
char source_adr[][4096], int source_adr_count,
@ -364,9 +370,9 @@ int libburner_payload(struct burn_drive *drive,
struct burn_track *track, *tracklist[99];
struct burn_progress progress;
time_t start_time;
int last_sector = 0, padding = 0, trackno, write_mode_tao = 0, fd;
int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd;
off_t fixed_size;
char *adr;
char *adr, reasons[1024];
struct stat stbuf;
if (all_tracks_type != BURN_AUDIO) {
@ -395,7 +401,7 @@ int libburner_payload(struct burn_drive *drive,
fixed_size = stbuf.st_size;
}
if (fixed_size==0)
write_mode_tao = 1;
unpredicted_size = 1;
data_src = NULL;
if (fd>=0)
data_src = burn_fd_source_new(fd, -1, fixed_size);
@ -419,9 +425,8 @@ int libburner_payload(struct burn_drive *drive,
/* Evaluate drive and media */
disc_state = burn_disc_get_status(drive);
if (disc_state == BURN_DISC_APPENDABLE) {
write_mode_tao = 1;
} else if (disc_state != BURN_DISC_BLANK) {
if (disc_state != BURN_DISC_BLANK &&
disc_state != BURN_DISC_APPENDABLE) {
if (disc_state == BURN_DISC_FULL) {
fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n");
if (burn_disc_erasable(drive))
@ -437,18 +442,17 @@ int libburner_payload(struct burn_drive *drive,
burn_options = burn_write_opts_new(drive);
burn_write_opts_set_perform_opc(burn_options, 0);
burn_write_opts_set_multi(burn_options, !!multi);
if (write_mode_tao)
burn_write_opts_set_write_type(burn_options,
BURN_WRITE_TAO, BURN_BLOCK_MODE1);
else
burn_write_opts_set_write_type(burn_options,
BURN_WRITE_SAO, BURN_BLOCK_SAO);
if(simulate_burn)
printf("\n*** Will TRY to SIMULATE burning ***\n\n");
burn_write_opts_set_simulate(burn_options, simulate_burn);
burn_structure_print_disc(target_disc);
burn_drive_set_speed(drive, 0, 0);
burn_write_opts_set_underrun_proof(burn_options, 1);
if (burn_write_opts_auto_write_type(burn_options, target_disc,
reasons, 0) == BURN_WRITE_NONE) {
fprintf(stderr, "FATAL: Failed to find a suitable write mode with this media.\n");
fprintf(stderr, "Reasons given:\n%s\n", reasons);
return 0;
}
printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
start_time = time(0);
@ -462,7 +466,7 @@ int libburner_payload(struct burn_drive *drive,
printf(
"Thank you for being patient since %d seconds.\n",
(int) (time(0) - start_time));
else if(write_mode_tao)
else if(unpredicted_size)
printf("Track %d : sector %d\n", progress.track+1,
progress.sector);
else
@ -590,9 +594,11 @@ int libburner_setup(int argc, char **argv)
printf(" %s --drive /dev/hdc my_image_file\n", argv[0]);
printf("Blank a used CD-RW (is combinable with burning in one run):\n");
printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]);
printf("Format a DVD-RW once before first use with libburner:\n");
printf("Blank a used DVD-RW (is combinable with burning in one run):\n");
printf(" %s --drive /dev/hdc --blank_full\n",argv[0]);
printf("Format a DVD-RW to avoid need for blanking before re-use:\n");
printf(" %s --drive /dev/hdc --format_overwrite\n", argv[0]);
printf("Burn two audio tracks:\n");
printf("Burn two audio tracks (to CD only):\n");
printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n");
printf(" test/dewav /path/to/track2.wav -o track2.cd\n");
printf(" %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]);

View File

@ -5,9 +5,9 @@
/** Overview
telltoc is a minimal demo application for the library libburn as provided
on http://libburn.pykix.org . It can list the available devices, can display
some drive properties, the type of media, eventual table of content and
multisession info for mkisofs option -C .
on http://libburnia.pykix.org . It can list the available devices, can
display some drive properties, the type of media, eventual table of content
and multisession info for mkisofs option -C .
It's main purpose, nevertheless, is to show you how to use libburn and also
to serve the libburn team as reference application. telltoc.c does indeed
define the standard way how above gestures can be implemented and stay upward
@ -228,6 +228,7 @@ int telltoc_media(struct burn_drive *drive)
double max_speed = 0.0, min_speed = 0.0, speed_conv;
enum burn_disc_status s;
char profile_name[80], speed_unit[40];
struct burn_multi_caps *caps;
printf("Media current: ");
ret = burn_disc_get_profile(drive, &profile_no, profile_name);
@ -273,6 +274,44 @@ int telltoc_media(struct burn_drive *drive)
} else
printf("is not recognizable\n");
ret = burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
if (ret > 0) {
printf("Write multi : ");
printf("%s multi-session , ",
caps->multi_session == 1 ? "allows" : "prohibits");
if (caps->multi_track)
printf("allows multiple tracks\n");
else
printf("enforces single track\n");
printf("Write start : ");
if (caps->start_adr == 1)
printf(
"allows addresses [%.f , %.f]s , alignment=%.fs\n",
(double) caps->start_range_low / 2048 ,
(double) caps->start_range_high / 2048 ,
(double) caps->start_alignment / 2048 );
else
printf("prohibits write start addressing\n");
printf("Write modes : ");
if (caps->might_do_tao)
printf("TAO%s",
caps->advised_write_mode == BURN_WRITE_TAO ?
" (advised)" : "");
if (caps->might_do_sao)
printf("%sSAO%s",
caps->might_do_tao ? " , " : "",
caps->advised_write_mode == BURN_WRITE_SAO ?
" (advised)" : "");
if (caps->might_do_raw)
printf("%sRAW%s",
caps->might_do_tao | caps->might_do_sao ?
" , " : "",
caps->advised_write_mode == BURN_WRITE_RAW ?
" (advised)" : "");
printf("\n");
burn_disc_free_multi_caps(&caps);
}
ret= burn_drive_get_write_speed(drive);
max_speed = ((double ) ret) / speed_conv;
ret= burn_drive_get_min_write_speed(drive);
@ -375,7 +414,7 @@ int telltoc_formatlist(struct burn_drive *drive)
int telltoc_toc(struct burn_drive *drive)
{
int num_sessions = 0 , num_tracks = 0 , lba = 0;
int num_sessions = 0 , num_tracks = 0 , lba = 0, pmin, psec, pframe;
int track_count = 0;
int session_no, track_no;
struct burn_disc *disc= NULL;
@ -397,27 +436,36 @@ int telltoc_toc(struct burn_drive *drive)
for(track_no= 0; track_no<num_tracks; track_no++) {
track_count++;
burn_track_get_entry(tracks[track_no], &toc_entry);
lba= burn_msf_to_lba(toc_entry.pmin, toc_entry.psec,
toc_entry.pframe);
if (toc_entry.extensions_valid & 1) {
/* DVD extension valid */
lba = toc_entry.start_lba;
burn_lba_to_msf(lba, &pmin, &psec, &pframe);
} else {
pmin = toc_entry.pmin;
psec = toc_entry.psec;
pframe = toc_entry.pframe;
lba= burn_msf_to_lba(pmin, psec, pframe);
}
printf("Media content: session %2d ", session_no+1);
printf("track %2d %s lba: %9d %2.2u:%2.2u:%2.2u\n",
printf("track %2d %s lba: %9d %4.2d:%2.2d:%2.2d\n",
track_count,
((toc_entry.control&7)<4?"audio":"data "),
lba,
toc_entry.pmin,
toc_entry.psec,
toc_entry.pframe);
lba, pmin, psec, pframe);
}
burn_session_get_leadout_entry(sessions[session_no],
&toc_entry);
lba = burn_msf_to_lba(toc_entry.pmin,
toc_entry.psec, toc_entry.pframe);
if (toc_entry.extensions_valid & 1) {
lba = toc_entry.start_lba;
burn_lba_to_msf(lba, &pmin, &psec, &pframe);
} else {
pmin = toc_entry.pmin;
psec = toc_entry.psec;
pframe = toc_entry.pframe;
lba= burn_msf_to_lba(pmin, psec, pframe);
}
printf("Media content: session %2d ", session_no+1);
printf("leadout lba: %9d %2.2u:%2.2u:%2.2u\n",
lba,
toc_entry.pmin,
toc_entry.psec,
toc_entry.pframe);
printf("leadout lba: %9d %4.2d:%2.2d:%2.2d\n",
lba, pmin, psec, pframe);
}
if (disc!=NULL)
burn_disc_free(disc);
@ -428,13 +476,8 @@ int telltoc_toc(struct burn_drive *drive)
int telltoc_msinfo(struct burn_drive *drive,
int msinfo_explicit, int msinfo_alone)
{
int num_sessions, session_no, ret, num_tracks;
int nwa = -123456789, lba = -123456789, aux_lba, lout_lba;
int ret, lba, nwa = -123456789, aux_lba;
enum burn_disc_status s;
struct burn_disc *disc= NULL;
struct burn_session **sessions;
struct burn_track **tracks;
struct burn_toc_entry toc_entry;
struct burn_write_opts *o= NULL;
s = burn_disc_get_status(drive);
@ -450,29 +493,12 @@ int telltoc_msinfo(struct burn_drive *drive,
The first number is the sector number of the first sector in
the last session of the disk that should be appended to.
*/
disc = burn_drive_get_disc(drive);
if (disc==NULL) {
fprintf(stderr,"SORRY: Cannot obtain info about CD content\n");
return 2;
}
sessions = burn_disc_get_sessions(disc, &num_sessions);
for (session_no = 0; session_no<num_sessions; session_no++) {
tracks = burn_session_get_tracks(sessions[session_no],
&num_tracks);
if (tracks==NULL || num_tracks<=0)
continue;
burn_track_get_entry(tracks[0], &toc_entry);
lba= burn_msf_to_lba(toc_entry.pmin, toc_entry.psec,
toc_entry.pframe);
}
if(lba==-123456789) {
fprintf(stderr,"SORRY: Cannot find any track on media\n");
ret = burn_disc_get_msc1(drive, &lba);
if (ret <= 0) {
fprintf(stderr,
"SORRY: Cannot obtain start address of last session\n");
{ ret = 0; goto ex; }
}
/* Prepare a qualified guess as fallback for nwa inquiry */
burn_session_get_leadout_entry(sessions[num_sessions-1], &toc_entry);
lout_lba= burn_msf_to_lba(toc_entry.pmin,toc_entry.psec,
toc_entry.pframe);
/* man mkisofs , option -C :
The second number is the starting sector number of the new session.
@ -489,21 +515,15 @@ int telltoc_msinfo(struct burn_drive *drive,
telltoc_regrab(drive); /* necessary to calm down my NEC drive */
if(ret<=0) {
fprintf(stderr,
"NOTE: Guessing next writeable address from leadout\n");
if(num_sessions>0)
nwa= lout_lba+6900;
else
nwa= lout_lba+11400;
"SORRY: Cannot obtain next writeable address\n");
{ ret = 0; goto ex; }
}
if (!msinfo_alone)
printf("Media msinfo : mkisofs ... -C ");
printf("%d,%d\n",lba,nwa);
ret = 1;
ex:;
if (disc!=NULL)
burn_disc_free(disc);
if (o!=NULL)
burn_write_opts_free(o);
return ret;
@ -615,7 +635,7 @@ int main(int argc, char **argv)
full_default = do_media = do_msinfo = do_capacities= do_toc = 1;
}
fprintf(stderr, "Initializing libburn.pykix.org ...\n");
fprintf(stderr, "Initializing libburnia.pykix.org ...\n");
if (burn_initialize())
fprintf(stderr, "Done\n");
else {