Compare commits
4 Commits
ZeroThreeT
...
ZeroTwoSix
Author | SHA1 | Date | |
---|---|---|---|
9ab5290059 | |||
ec1aa0c49a | |||
80639a7749 | |||
8c82e3c437 |
@ -1,5 +1,2 @@
|
|||||||
Joe Neeman
|
Joe Neeman
|
||||||
Philippe Rouquier
|
Philippe Rouquier
|
||||||
Gabriel Craciunescu
|
|
||||||
George Danchev
|
|
||||||
Jean-Francois Wauthy
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
|
Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
|
||||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
||||||
Mario Danic <mario.danic@gmail.com>, Thomas Schmitt <scdbackup@gmx.net>
|
Mario Danic <mario.danic@gmail.com>, Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Copyright (C) 2006-2007 Mario Danic, Thomas Schmitt
|
Copyright (C) 2006 Mario Danic, Thomas Schmitt
|
||||||
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
234
INSTALL
234
INSTALL
@ -1,234 +0,0 @@
|
|||||||
Installation Instructions
|
|
||||||
*************************
|
|
||||||
|
|
||||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
|
||||||
2006 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free documentation; the Free Software Foundation gives
|
|
||||||
unlimited permission to copy, distribute and modify it.
|
|
||||||
|
|
||||||
Basic Installation
|
|
||||||
==================
|
|
||||||
|
|
||||||
Briefly, the shell commands `./configure; make; make install' should
|
|
||||||
configure, build, and install this package. The following
|
|
||||||
more-detailed instructions are generic; see the `README' file for
|
|
||||||
instructions specific to this package.
|
|
||||||
|
|
||||||
The `configure' shell script attempts to guess correct values for
|
|
||||||
various system-dependent variables used during compilation. It uses
|
|
||||||
those values to create a `Makefile' in each directory of the package.
|
|
||||||
It may also create one or more `.h' files containing system-dependent
|
|
||||||
definitions. Finally, it creates a shell script `config.status' that
|
|
||||||
you can run in the future to recreate the current configuration, and a
|
|
||||||
file `config.log' containing compiler output (useful mainly for
|
|
||||||
debugging `configure').
|
|
||||||
|
|
||||||
It can also use an optional file (typically called `config.cache'
|
|
||||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
|
||||||
the results of its tests to speed up reconfiguring. Caching is
|
|
||||||
disabled by default to prevent problems with accidental use of stale
|
|
||||||
cache files.
|
|
||||||
|
|
||||||
If you need to do unusual things to compile the package, please try
|
|
||||||
to figure out how `configure' could check whether to do them, and mail
|
|
||||||
diffs or instructions to the address given in the `README' so they can
|
|
||||||
be considered for the next release. If you are using the cache, and at
|
|
||||||
some point `config.cache' contains results you don't want to keep, you
|
|
||||||
may remove or edit it.
|
|
||||||
|
|
||||||
The file `configure.ac' (or `configure.in') is used to create
|
|
||||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
|
||||||
you want to change it or regenerate `configure' using a newer version
|
|
||||||
of `autoconf'.
|
|
||||||
|
|
||||||
The simplest way to compile this package is:
|
|
||||||
|
|
||||||
1. `cd' to the directory containing the package's source code and type
|
|
||||||
`./configure' to configure the package for your system.
|
|
||||||
|
|
||||||
Running `configure' might take a while. While running, it prints
|
|
||||||
some messages telling which features it is checking for.
|
|
||||||
|
|
||||||
2. Type `make' to compile the package.
|
|
||||||
|
|
||||||
3. Optionally, type `make check' to run any self-tests that come with
|
|
||||||
the package.
|
|
||||||
|
|
||||||
4. Type `make install' to install the programs and any data files and
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
5. You can remove the program binaries and object files from the
|
|
||||||
source code directory by typing `make clean'. To also remove the
|
|
||||||
files that `configure' created (so you can compile the package for
|
|
||||||
a different kind of computer), type `make distclean'. There is
|
|
||||||
also a `make maintainer-clean' target, but that is intended mainly
|
|
||||||
for the package's developers. If you use it, you may have to get
|
|
||||||
all sorts of other programs in order to regenerate files that came
|
|
||||||
with the distribution.
|
|
||||||
|
|
||||||
Compilers and Options
|
|
||||||
=====================
|
|
||||||
|
|
||||||
Some systems require unusual options for compilation or linking that the
|
|
||||||
`configure' script does not know about. Run `./configure --help' for
|
|
||||||
details on some of the pertinent environment variables.
|
|
||||||
|
|
||||||
You can give `configure' initial values for configuration parameters
|
|
||||||
by setting variables in the command line or in the environment. Here
|
|
||||||
is an example:
|
|
||||||
|
|
||||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
|
||||||
|
|
||||||
*Note Defining Variables::, for more details.
|
|
||||||
|
|
||||||
Compiling For Multiple Architectures
|
|
||||||
====================================
|
|
||||||
|
|
||||||
You can compile the package for more than one kind of computer at the
|
|
||||||
same time, by placing the object files for each architecture in their
|
|
||||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
|
||||||
directory where you want the object files and executables to go and run
|
|
||||||
the `configure' script. `configure' automatically checks for the
|
|
||||||
source code in the directory that `configure' is in and in `..'.
|
|
||||||
|
|
||||||
With a non-GNU `make', it is safer to compile the package for one
|
|
||||||
architecture at a time in the source code directory. After you have
|
|
||||||
installed the package for one architecture, use `make distclean' before
|
|
||||||
reconfiguring for another architecture.
|
|
||||||
|
|
||||||
Installation Names
|
|
||||||
==================
|
|
||||||
|
|
||||||
By default, `make install' installs the package's commands under
|
|
||||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
|
||||||
can specify an installation prefix other than `/usr/local' by giving
|
|
||||||
`configure' the option `--prefix=PREFIX'.
|
|
||||||
|
|
||||||
You can specify separate installation prefixes for
|
|
||||||
architecture-specific files and architecture-independent files. If you
|
|
||||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
|
||||||
PREFIX as the prefix for installing programs and libraries.
|
|
||||||
Documentation and other data files still use the regular prefix.
|
|
||||||
|
|
||||||
In addition, if you use an unusual directory layout you can give
|
|
||||||
options like `--bindir=DIR' to specify different values for particular
|
|
||||||
kinds of files. Run `configure --help' for a list of the directories
|
|
||||||
you can set and what kinds of files go in them.
|
|
||||||
|
|
||||||
If the package supports it, you can cause programs to be installed
|
|
||||||
with an extra prefix or suffix on their names by giving `configure' the
|
|
||||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
|
||||||
|
|
||||||
Optional Features
|
|
||||||
=================
|
|
||||||
|
|
||||||
Some packages pay attention to `--enable-FEATURE' options to
|
|
||||||
`configure', where FEATURE indicates an optional part of the package.
|
|
||||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
|
||||||
is something like `gnu-as' or `x' (for the X Window System). The
|
|
||||||
`README' should mention any `--enable-' and `--with-' options that the
|
|
||||||
package recognizes.
|
|
||||||
|
|
||||||
For packages that use the X Window System, `configure' can usually
|
|
||||||
find the X include and library files automatically, but if it doesn't,
|
|
||||||
you can use the `configure' options `--x-includes=DIR' and
|
|
||||||
`--x-libraries=DIR' to specify their locations.
|
|
||||||
|
|
||||||
Specifying the System Type
|
|
||||||
==========================
|
|
||||||
|
|
||||||
There may be some features `configure' cannot figure out automatically,
|
|
||||||
but needs to determine by the type of machine the package will run on.
|
|
||||||
Usually, assuming the package is built to be run on the _same_
|
|
||||||
architectures, `configure' can figure that out, but if it prints a
|
|
||||||
message saying it cannot guess the machine type, give it the
|
|
||||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
|
||||||
type, such as `sun4', or a canonical name which has the form:
|
|
||||||
|
|
||||||
CPU-COMPANY-SYSTEM
|
|
||||||
|
|
||||||
where SYSTEM can have one of these forms:
|
|
||||||
|
|
||||||
OS KERNEL-OS
|
|
||||||
|
|
||||||
See the file `config.sub' for the possible values of each field. If
|
|
||||||
`config.sub' isn't included in this package, then this package doesn't
|
|
||||||
need to know the machine type.
|
|
||||||
|
|
||||||
If you are _building_ compiler tools for cross-compiling, you should
|
|
||||||
use the option `--target=TYPE' to select the type of system they will
|
|
||||||
produce code for.
|
|
||||||
|
|
||||||
If you want to _use_ a cross compiler, that generates code for a
|
|
||||||
platform different from the build platform, you should specify the
|
|
||||||
"host" platform (i.e., that on which the generated programs will
|
|
||||||
eventually be run) with `--host=TYPE'.
|
|
||||||
|
|
||||||
Sharing Defaults
|
|
||||||
================
|
|
||||||
|
|
||||||
If you want to set default values for `configure' scripts to share, you
|
|
||||||
can create a site shell script called `config.site' that gives default
|
|
||||||
values for variables like `CC', `cache_file', and `prefix'.
|
|
||||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
|
||||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
|
||||||
`CONFIG_SITE' environment variable to the location of the site script.
|
|
||||||
A warning: not all `configure' scripts look for a site script.
|
|
||||||
|
|
||||||
Defining Variables
|
|
||||||
==================
|
|
||||||
|
|
||||||
Variables not defined in a site shell script can be set in the
|
|
||||||
environment passed to `configure'. However, some packages may run
|
|
||||||
configure again during the build, and the customized values of these
|
|
||||||
variables may be lost. In order to avoid this problem, you should set
|
|
||||||
them in the `configure' command line, using `VAR=value'. For example:
|
|
||||||
|
|
||||||
./configure CC=/usr/local2/bin/gcc
|
|
||||||
|
|
||||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
|
||||||
overridden in the site shell script).
|
|
||||||
|
|
||||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
|
||||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
|
||||||
|
|
||||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
|
||||||
|
|
||||||
`configure' Invocation
|
|
||||||
======================
|
|
||||||
|
|
||||||
`configure' recognizes the following options to control how it operates.
|
|
||||||
|
|
||||||
`--help'
|
|
||||||
`-h'
|
|
||||||
Print a summary of the options to `configure', and exit.
|
|
||||||
|
|
||||||
`--version'
|
|
||||||
`-V'
|
|
||||||
Print the version of Autoconf used to generate the `configure'
|
|
||||||
script, and exit.
|
|
||||||
|
|
||||||
`--cache-file=FILE'
|
|
||||||
Enable the cache: use and save the results of the tests in FILE,
|
|
||||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
|
||||||
disable caching.
|
|
||||||
|
|
||||||
`--config-cache'
|
|
||||||
`-C'
|
|
||||||
Alias for `--cache-file=config.cache'.
|
|
||||||
|
|
||||||
`--quiet'
|
|
||||||
`--silent'
|
|
||||||
`-q'
|
|
||||||
Do not print messages saying which checks are being made. To
|
|
||||||
suppress all normal output, redirect it to `/dev/null' (any error
|
|
||||||
messages will still be shown).
|
|
||||||
|
|
||||||
`--srcdir=DIR'
|
|
||||||
Look for the package's source code in directory DIR. Usually
|
|
||||||
`configure' can determine that directory automatically.
|
|
||||||
|
|
||||||
`configure' also accepts some other, not widely useful, options. Run
|
|
||||||
`configure --help' for more details.
|
|
||||||
|
|
@ -101,9 +101,9 @@ test_structest_CPPFLAGS = -Ilibburn
|
|||||||
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||||
test_structest_SOURCES = test/structest.c
|
test_structest_SOURCES = test/structest.c
|
||||||
|
|
||||||
## cdrskin construction site - ts A60816 - A70210
|
## cdrskin construction site - ts A60816
|
||||||
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
|
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
|
||||||
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_3_2
|
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_2_6
|
||||||
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
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
|
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
|
||||||
##
|
##
|
||||||
@ -180,7 +180,6 @@ EXTRA_DIST = \
|
|||||||
cdrskin/README \
|
cdrskin/README \
|
||||||
cdrskin/cdrecord_spy.sh \
|
cdrskin/cdrecord_spy.sh \
|
||||||
cdrskin/compile_cdrskin.sh \
|
cdrskin/compile_cdrskin.sh \
|
||||||
cdrskin/convert_man_to_html.sh \
|
|
||||||
cdrskin/changelog.txt \
|
cdrskin/changelog.txt \
|
||||||
cdrskin/cdrskin_eng.html \
|
cdrskin/cdrskin_eng.html \
|
||||||
cdrskin/wiki_plain.txt \
|
cdrskin/wiki_plain.txt \
|
||||||
@ -191,8 +190,5 @@ EXTRA_DIST = \
|
|||||||
libburn/sg-freebsd.c \
|
libburn/sg-freebsd.c \
|
||||||
libburn/sg-linux.c \
|
libburn/sg-linux.c \
|
||||||
COPYING \
|
COPYING \
|
||||||
NEWS \
|
|
||||||
ChangeLog \
|
|
||||||
INSTALL \
|
|
||||||
$(man_MANS)
|
$(man_MANS)
|
||||||
|
|
||||||
|
76
README
76
README
@ -1,25 +1,25 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
libburnia.pykix.org
|
libburn.pykix.org
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
This all is under GPL.
|
This all is under GPL.
|
||||||
(See GPL reference, our clarification and commitment at the end of this text)
|
(See GPL reference, our clarification and commitment at the end of this text)
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
libburnia.pykix.org
|
libburn.pykix.org
|
||||||
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Copyright (C) 2006-2007 Mario Danic, Thomas Schmitt
|
Copyright (C) 2006 Mario Danic, Thomas Schmitt
|
||||||
|
|
||||||
Still containing parts of
|
Still containing parts of
|
||||||
Libburn. By Derek Foreman <derek@signalmarketing.com> and
|
Libburn. By Derek Foreman <derek@signalmarketing.com> and
|
||||||
Ben Jansens <xor@orodu.net>
|
Ben Jansens <xor@orodu.net>
|
||||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
||||||
These parts are to be replaced by own code of above libburnia.pykix.org
|
These parts are to be replaced by own code of above libburn.pykix.org-copyright
|
||||||
copyright holders and then libburnia.pykix.org is to be their sole copyright.
|
holders and then libburn.pykix.org is to be their sole copyright.
|
||||||
This is done to achieve the right to issue the clarification and the
|
This is done to achieve the right to issue the clarification and the
|
||||||
commitment as written at the end of this text.
|
commitment as written at the end of this text.
|
||||||
The rights and merits of the Libburn-copyright holders Derek Foreman and
|
The rights and merits of the Libburn-copyright holders Derek Foreman and
|
||||||
Ben Jansens will be duely respected.
|
Ben Jansens will be duely respected.
|
||||||
|
|
||||||
This libburnia.pykix.org toplevel README (C) 2006-2007 Thomas Schmitt
|
This libburn.pykix.org toplevel README (C) 2006 Thomas Schmitt
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
Build and Installation
|
Build and Installation
|
||||||
@ -27,14 +27,14 @@ This libburnia.pykix.org toplevel README (C) 2006-2007 Thomas Schmitt
|
|||||||
Our build system is based on autotools. For preparing the build of a SVN
|
Our build system is based on autotools. For preparing the build of a SVN
|
||||||
snapshot you will need autotools of at least version 1.7.
|
snapshot you will need autotools of at least version 1.7.
|
||||||
Check out from SVN by
|
Check out from SVN by
|
||||||
svn co http://libburnia-svn.pykix.org/libburn/trunk libburn_pykix
|
svn co http://libburn-svn.pykix.org/libburn/trunk libburn_pykix
|
||||||
go into directory libburn_pykix and apply autotools by
|
go into directory libburn_pykix and apply autotools by
|
||||||
./bootstrap
|
./bootstrap
|
||||||
|
|
||||||
Alternatively you may unpack a release tarball for which you do not need
|
Alternatively you may unpack a release tarball for which you do not need
|
||||||
autotools installed.
|
autotools installed.
|
||||||
|
|
||||||
To build a libburnia.pykix.org subproject it should be sufficient to go
|
To build libburn.pykix.org and its subprojects it should be sufficient to go
|
||||||
into its toplevel directory (here: "libburn_pykix") and execute
|
into its toplevel directory (here: "libburn_pykix") and execute
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
@ -43,19 +43,18 @@ To make the libraries accessible for running resp. developing applications
|
|||||||
make install
|
make install
|
||||||
|
|
||||||
|
|
||||||
The other half of the project, libisofs, is hosted in the libburnia SVN, too:
|
The other half of the project, libisofs, is hosted in the libburn SVN, too:
|
||||||
svn co http://libburnia-svn.pykix.org/libisofs/trunk libisofs_pykix
|
svn co http://libburn-svn.pykix.org/libisofs/trunk libisofs_pykix
|
||||||
See README file there.
|
See README file there.
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
Overview of libburnia.pykix.org
|
Overview of libburn.pykix.org
|
||||||
|
|
||||||
libburnia.pykix.org is an open-source software project for reading, mastering
|
libburn.pykix.org is an open-source software project for reading, mastering and
|
||||||
and writing optical discs.
|
writing optical discs. For now this means only CD-R and CD-RW.
|
||||||
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
|
The project comprises of several more or less interdependent parts which
|
||||||
together strive to be a usable foundation for application development.
|
together strive to be a usable foundation for application development.
|
||||||
@ -67,11 +66,11 @@ 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,
|
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
|
||||||
volunteers for testing of realistic use cases.
|
volunteers for testing of realistic use cases.
|
||||||
|
|
||||||
We have a workable code base for burning CD and most single layer DVD.
|
We do have a workable code base for burning data CDs, though. The burn API is
|
||||||
The burn API is quite comprehensively documented and can be used to build a
|
quite comprehensively documented and can be used to build a presentable
|
||||||
presentable application.
|
application.
|
||||||
We have a functional binary which emulates parts of cdrecord in order to
|
We do 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
|
prove that usability, and in order to allow you to explore libburn's scope
|
||||||
by help of existing cdrecord frontends.
|
by help of existing cdrecord frontends.
|
||||||
|
|
||||||
The project components (list subject to growth, hopefully):
|
The project components (list subject to growth, hopefully):
|
||||||
@ -79,25 +78,20 @@ The project components (list subject to growth, hopefully):
|
|||||||
- libburn is the library by which preformatted data get onto optical media.
|
- 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
|
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
|
||||||
/dev/hdX (e.g. on kernel 2.6).
|
/dev/hdX (e.g. on kernel 2.6).
|
||||||
libburn is the foundation of our cdrecord emulation. Its code is
|
libburn is the foundation of our cdrecord emulation.
|
||||||
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
|
- libisofs is the library to pack up hard disk files and directories into a
|
||||||
ISO 9660 disk image. This may then be brought to media via libburn.
|
ISO 9660 disk image. This may then be brought to CD via libburn.
|
||||||
libisofs is to be the foundation of our upcoming mkisofs emulation.
|
libisofs is to be the foundation of our upcoming mkisofs emulation.
|
||||||
|
|
||||||
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
||||||
Cdrecord is a powerful GPL'ed burn program included in Joerg
|
Cdrecord is a powerful GPL'ed burn program included in Joerg
|
||||||
Schilling's cdrtools. cdrskin strives to be a second source for
|
Schilling's cdrtools. cdrskin strives to be a second source for
|
||||||
the services traditionally provided by cdrecord. Additionally it
|
the services traditionally provided by cdrecord.
|
||||||
provides libburn's DVD capabilities, where only -sao is compatible
|
|
||||||
with cdrecord.
|
|
||||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||||
Many bytes have been copied from the message output of cdrecord
|
Many bytes have been copied from the message output of cdrecord
|
||||||
runs, though.
|
runs, though.
|
||||||
See cdrskin/README and man cdrskin/cdrskin.1 for more.
|
See cdrskin/README for more.
|
||||||
|
|
||||||
- test is a collection of application gestures and examples given by the
|
- test is a collection of application gestures and examples given by the
|
||||||
authors of the library features. The main API example for libburn
|
authors of the library features. The main API example for libburn
|
||||||
@ -175,26 +169,6 @@ Project history as far as known to me:
|
|||||||
|
|
||||||
- 13th November 2006 splitting releases of libburn+cdrskin from libisofs.
|
- 13th November 2006 splitting releases of libburn+cdrskin from libisofs.
|
||||||
|
|
||||||
- 24th November 2006 release of libburn-0.2.6 and cdrskin-0.2.6 . cdrskin has
|
|
||||||
become suitable for unaware frontends as long as they perform only the core
|
|
||||||
of cdrecord use cases (including open-ended input streams, audio, and
|
|
||||||
multi-session).
|
|
||||||
|
|
||||||
- 28th November 2006 the umbrella project which encloses both, libisofs and
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
@ -213,9 +187,9 @@ Project history as far as known to me:
|
|||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
Clarification in my name and in the name of Mario Danic, upcoming copyright
|
Clarification in my name and in the name of Mario Danic, upcoming copyright
|
||||||
holders on toplevel of libburnia. To be fully in effect after the remaining
|
holders on toplevel of libburn. To be fully in effect after the remaining other
|
||||||
other copyrighted code has been replaced by ours and by copyright-free
|
copyrighted code has been replaced by ours and by copyright-free contributions
|
||||||
contributions of our friends:
|
of our friends:
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
We, the copyright holders, agree on the interpretation that
|
We, the copyright holders, agree on the interpretation that
|
||||||
|
171
cdrskin/README
171
cdrskin/README
@ -1,5 +1,5 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
libburnia.pykix.org scdbackup.sourceforge.net/cdrskin_eng.html
|
libburn.pykix.org scdbackup.sourceforge.net/cdrskin_eng.html
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
Installation instructions at about line 60. First the legal stuff:
|
Installation instructions at about line 60. First the legal stuff:
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@ -7,31 +7,31 @@ This all is under GPL.
|
|||||||
(See GPL reference, our clarification and commitment at the end of this text)
|
(See GPL reference, our clarification and commitment at the end of this text)
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
Based on and sub project of:
|
Based on and sub project of:
|
||||||
libburnia.pykix.org
|
libburn.pykix.org
|
||||||
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Copyright (C) 2006-2007 Mario Danic, Thomas Schmitt
|
Copyright (C) 2006 Mario Danic, Thomas Schmitt
|
||||||
|
|
||||||
libburnia.pykix.org is inspired by and in other components still containing
|
libburn.pykix.org is inspired by and in other components still containing
|
||||||
parts of
|
parts of
|
||||||
Libburn. By Derek Foreman <derek@signalmarketing.com> and
|
Libburn. By Derek Foreman <derek@signalmarketing.com> and
|
||||||
Ben Jansens <xor@orodu.net>
|
Ben Jansens <xor@orodu.net>
|
||||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
||||||
See toplevel README for an overview of the current copyright situation in
|
See toplevel README for an overview of the current copyright situation in
|
||||||
libburnia.pykix.org.
|
libburn.pykix.org.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
My thanks to the above authors (except myself, of course) for making the
|
My thanks to the above authors (except myself, of course) for making the
|
||||||
following possible.
|
following possible.
|
||||||
|
|
||||||
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
|
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Integrated sub project of libburnia.pykix.org but also published via:
|
Integrated sub project of libburn.pykix.org but also published via:
|
||||||
http://scdbackup.sourceforge.net/cdrskin_eng.html
|
http://scdbackup.sourceforge.net/cdrskin_eng.html
|
||||||
http://scdbackup.sourceforge.net/cdrskin-0.3.2.pl00.tar.gz
|
http://scdbackup.sourceforge.net/cdrskin-0.2.6.pl01.tar.gz
|
||||||
Copyright (C) 2006-2007 Thomas Schmitt
|
Copyright (C) 2006 Thomas Schmitt
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
On top of libburn there is implemented cdrskin 0.3.2, a limited cdrecord
|
On top of libburn there is implemented cdrskin 0.2.6, a limited cdrecord
|
||||||
compatibility wrapper which allows to use some libburn features from
|
compatibility wrapper which allows to use some libburn features from
|
||||||
the command line.
|
the command line.
|
||||||
Interested users of cdrecord are invited to participate in the development
|
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
|
Compilation, First Glimpse, Installation
|
||||||
|
|
||||||
Obtain cdrskin-0.3.2.pl00.tar.gz, take it to a directory of your choice and do:
|
Obtain cdrskin-0.2.6.pl02.tar.gz, take it to a directory of your choice and do:
|
||||||
|
|
||||||
tar xzf cdrskin-0.3.2.pl00.tar.gz
|
tar xzf cdrskin-0.2.6.pl02.tar.gz
|
||||||
cd cdrskin-0.3.2
|
cd cdrskin-0.2.6
|
||||||
|
|
||||||
Or obtain a libburnia.pykix.org SVN snapshot,
|
Or obtain a libburn.pykix.org SVN snapshot,
|
||||||
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
|
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
|
||||||
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
|
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
|
||||||
|
|
||||||
Within that toplevel directory of either cdrskin-0.3.2 or libburn then execute:
|
Within that toplevel directory of either cdrskin-0.2.6 or libburn then execute:
|
||||||
|
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
@ -143,52 +143,41 @@ It is not checked for the necessary degree of hacker safety.
|
|||||||
|
|
||||||
Usage examples
|
Usage examples
|
||||||
|
|
||||||
For options and recordable media classes see
|
|
||||||
man 1 cdrskin
|
|
||||||
|
|
||||||
Get an overview of cdrecord style addresses of available devices
|
Get an overview of cdrecord style addresses of available devices
|
||||||
cdrskin -scanbus
|
cdrskin -scanbus
|
||||||
cdrskin dev=ATA -scanbus
|
cdrskin dev=ATA -scanbus
|
||||||
cdrskin --devices
|
|
||||||
|
|
||||||
Adresses reported with dev=ATA need prefix "ATA:". Address examples:
|
Note: Adresses reported with dev=ATA are to be used with prefix "ATA:". You may
|
||||||
dev=0,1,0 dev=ATA:1,0,0 dev=/dev/sg1 dev=/dev/hdc
|
well use device file addresses as reported with --devices. Examples:
|
||||||
See also "Drive Addressing" below.
|
dev=0,1,0 dev=/dev/sg1 dev=ATA:1,0,0 dev=/dev/hdc
|
||||||
|
See also "Drive Addressing".
|
||||||
|
Note: Address numbers have changed since cdrskin-0.2.2 in order to become
|
||||||
|
compatible with cdrecord numbers. To get the old number scheme, use
|
||||||
|
option --old_pseudo_scsi_adr . See also "Pseudo-SCSI Adresses".
|
||||||
|
Sorry for any inconvenience.
|
||||||
|
|
||||||
|
|
||||||
Obtain some info about the drive
|
Obtain some info about the drive
|
||||||
cdrskin dev=0,1,0 -checkdrive
|
cdrskin dev=0,1,0 -checkdrive
|
||||||
|
|
||||||
Obtain some info about the drive and the inserted media
|
Obtain some info about the drive and the inserted media
|
||||||
cdrskin dev=0,1,0 -atip -v
|
cdrskin dev=0,1,0 -atip
|
||||||
|
|
||||||
Make used CD-RW or used unformatted DVD-RW writeable again
|
Thoroughly blank a CD-RW
|
||||||
|
cdrskin -v dev=0,1,0 blank=all -eject
|
||||||
|
|
||||||
|
Blank CD-RW sufficiently for making it ready for overwrite
|
||||||
cdrskin -v dev=0,1,0 blank=fast -eject
|
cdrskin -v dev=0,1,0 blank=fast -eject
|
||||||
|
|
||||||
Format DVD-RW to avoid need for blanking before re-use
|
Burn image file my_image.iso to CD
|
||||||
cdrskin -v dev=0,1,0 blank=format_overwrite
|
cdrskin -v dev=0,1,0 speed=12 fs=8m -sao driveropts=burnfree padsize=300k \
|
||||||
|
|
||||||
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
|
-eject my_image.iso
|
||||||
|
|
||||||
Write several sessions to the same CD or DVD-R[W]
|
Burn a compressed afio archive to CD on-the-fly
|
||||||
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 \
|
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 -tao \
|
||||||
driveropts=burnfree padsize=300k -
|
driveropts=burnfree padsize=300k -
|
||||||
|
|
||||||
Burn 6 audio tracks from files with different formats to CD (not to any DVD).
|
Burn 6 audio tracks from files with different formats to CD.
|
||||||
Anything except .wav or .au files has to be converted into raw format first.
|
Anything except .wav or .au files has to be converted into raw format first.
|
||||||
See below "Audio CD" for specifications.
|
See below "Audio CD" for specifications.
|
||||||
ogg123 -d raw -f track01.cd /path/to/track1.ogg
|
ogg123 -d raw -f track01.cd /path/to/track1.ogg
|
||||||
@ -224,12 +213,9 @@ Run a backup :
|
|||||||
Restrictions
|
Restrictions
|
||||||
|
|
||||||
The major restrictions are lifted now: audio, TAO, multi-session do work.
|
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 restricted to single layer overwriteable DVD (-RAM, +RW, -RW)
|
If you have use cases for them, please report your wishes and expectations.
|
||||||
for now.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -249,10 +235,6 @@ 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.
|
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.
|
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
|
Drive Addressing
|
||||||
|
|
||||||
@ -348,7 +330,6 @@ If not --no_rc is the first argument then cdrskin attempts on startup to read
|
|||||||
arguments from the following three files:
|
arguments from the following three files:
|
||||||
/etc/default/cdrskin
|
/etc/default/cdrskin
|
||||||
/etc/opt/cdrskin/rc
|
/etc/opt/cdrskin/rc
|
||||||
/etc/cdrskin/cdrskin.conf
|
|
||||||
$HOME/.cdrskinrc
|
$HOME/.cdrskinrc
|
||||||
The files are read in the sequence given above.
|
The files are read in the sequence given above.
|
||||||
Each readable line is treated as one single argument. No extra blanks.
|
Each readable line is treated as one single argument. No extra blanks.
|
||||||
@ -361,7 +342,7 @@ dev=0,1,0
|
|||||||
dev_translation=+1,0,0+0,1,0
|
dev_translation=+1,0,0+0,1,0
|
||||||
|
|
||||||
# Some more options
|
# Some more options
|
||||||
fifo_start_at=0
|
--fifo_start_empty
|
||||||
fs=16m
|
fs=16m
|
||||||
|
|
||||||
|
|
||||||
@ -391,90 +372,6 @@ I myself am not into audio. So libburn-hackers@pykix.org might be the
|
|||||||
best address for suggestions, requests and bug reports.
|
best address for suggestions, requests and bug reports.
|
||||||
|
|
||||||
|
|
||||||
DVD+RW and DVD-RAM
|
|
||||||
|
|
||||||
DVD+RW and DVD-RAM media get treated as blank media regardless wether they
|
|
||||||
hold data or not. 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.
|
|
||||||
|
|
||||||
For these media, -msinfo alone would not be enough to perform appending of an
|
|
||||||
ISO filesystem. The filesystem driver will need a hint to find the start of the
|
|
||||||
most recent session. For example put an ISO filesystem at address 1 GB:
|
|
||||||
mkisofs -C 0,524288 ... | \
|
|
||||||
cdrskin dev=/dev/sr0 -v fs=32m -eject speed=4 write_start_address=524288s -
|
|
||||||
The superuser may then do:
|
|
||||||
mount -t iso9660 -o ro,sbsector=524288 /dev/sr0 /mnt
|
|
||||||
Note: On my linux-2.4.21-215 mount works only with sbsector <= 337920 (660 MB).
|
|
||||||
To extend a filesystem already existing at address 0
|
|
||||||
mkisofs -C 0,524288 -M /dev/sr0 ... | cdrskin dev=/dev/sr0 ...
|
|
||||||
Record the number 524288 for usage as first number with -C at the next
|
|
||||||
extension:
|
|
||||||
mkisofs -C 524288,1000000 ... | cdrskin write_start_address=1000000s ...
|
|
||||||
|
|
||||||
Program growisofs can append to an ISO filesystem on DVD+RW by additionally
|
|
||||||
manipulating the first session. cdrskin does not want to get involved so deep
|
|
||||||
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 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.
|
|
||||||
|
|
||||||
"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.
|
|
||||||
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, dvd+rw-format or cdrskin. Perils of DVD-RW.
|
|
||||||
|
|
||||||
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
|
|
||||||
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. 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
|
Special compilation variations
|
||||||
|
|
||||||
You may get a (super fat) statically linked binary by :
|
You may get a (super fat) statically linked binary by :
|
||||||
|
@ -20,28 +20,27 @@ set -x
|
|||||||
# The script is to be run in the directory above the toplevel
|
# The script is to be run in the directory above the toplevel
|
||||||
# directory of libburn resp. cdrskin development.
|
# 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:
|
# Downloaded by:
|
||||||
# $ svn co http://libburnia-svn.pykix.org/libburn/tags/... $intermediate
|
# $ svn co http://libburn-svn.pykix.org/trunk libburn_pykix
|
||||||
# packed up in a tarball just to save it from inadverted changes by
|
# packed up in a tarball just to save it from inadverted changes by
|
||||||
# $ tar czf libburn_svn.tgz $intermediate
|
# $ tar czf libburn_svn.tgz libburn_pykix
|
||||||
original="./libburn_svn.tgz"
|
original="./libburn_svn.tgz"
|
||||||
# Historic moments:
|
# Historic moments:
|
||||||
# original="./libburn_svn_A60815.tgz"
|
# original="./libburn_svn_A60815.tgz"
|
||||||
# original="./libburn_cdrskin_A60819.tgz"
|
# original="./libburn_cdrskin_A60819.tgz"
|
||||||
|
|
||||||
|
# The top level directory in that snapshot is named
|
||||||
|
intermediate="./libburn_pykix"
|
||||||
|
|
||||||
# My changes are in $changes , mainly in $changes/cdrskin
|
# My changes are in libburn-0.2.3.ts.develop , mainly in ./cdrskin
|
||||||
changes="./libburn-develop"
|
|
||||||
|
|
||||||
skin_release="0.3.3"
|
changes="./libburn-0.2.3.ts.develop"
|
||||||
patch_level=""
|
skin_release="0.2.6"
|
||||||
|
patch_level=".pl01"
|
||||||
skin_rev="$skin_release""$patch_level"
|
skin_rev="$skin_release""$patch_level"
|
||||||
|
|
||||||
|
|
||||||
# The result directory and the name of the result tarballs
|
# The result directory and the name of the result tarballs
|
||||||
target="./cdrskin-${skin_release}"
|
target="./cdrskin-${skin_release}"
|
||||||
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
|
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
|
||||||
@ -55,9 +54,6 @@ compile_cmd="./cdrskin/compile_cdrskin.sh"
|
|||||||
compile_static_opts="-static"
|
compile_static_opts="-static"
|
||||||
compile_result="cdrskin/cdrskin"
|
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_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
|
||||||
bintarget_static="$bintarget_dynamic"-static
|
bintarget_static="$bintarget_dynamic"-static
|
||||||
|
|
||||||
@ -126,8 +122,6 @@ do
|
|||||||
rm "$cdrskin_target"/cdrskin_"$i"
|
rm "$cdrskin_target"/cdrskin_"$i"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Remove eventual SVN stuff from cdrskin directory
|
|
||||||
for i in .deps .dirstamp .libs
|
for i in .deps .dirstamp .libs
|
||||||
do
|
do
|
||||||
if test -e "$cdrskin_target"/"$i"
|
if test -e "$cdrskin_target"/"$i"
|
||||||
@ -136,23 +130,6 @@ do
|
|||||||
fi
|
fi
|
||||||
done
|
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)
|
# Remove unwanted SVN stuff (TODO: avoid downloading it)
|
||||||
for i in "$target"/.svn "$target"/*/.svn
|
for i in "$target"/.svn "$target"/*/.svn
|
||||||
do
|
do
|
||||||
@ -167,6 +144,12 @@ do
|
|||||||
fi
|
fi
|
||||||
done
|
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
|
# Make SVN state tarball for the libburn team
|
||||||
tar czf "$cdrskin_tarball_svn" "$target"
|
tar czf "$cdrskin_tarball_svn" "$target"
|
||||||
@ -196,20 +179,18 @@ done
|
|||||||
# Pack it up to the new libburn+cdrskin-tarball
|
# Pack it up to the new libburn+cdrskin-tarball
|
||||||
tar czf "$cdrskin_tarball" "$target"
|
tar czf "$cdrskin_tarball" "$target"
|
||||||
|
|
||||||
# Produce a static and a dynamic binary, and a HTML man page
|
# Produce a static and a dynamic binary
|
||||||
(
|
(
|
||||||
cd "$compile_dir" || exit 1
|
cd "$compile_dir" || exit 1
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
"$compile_cmd" -do_strip
|
$compile_cmd -do_strip
|
||||||
cp "$compile_result" "../$bintarget_dynamic"
|
cp "$compile_result" "../$bintarget_dynamic"
|
||||||
if test -n "$compile_static_opts"
|
if test -n "$compile_static_opts"
|
||||||
then
|
then
|
||||||
"$compile_cmd" $compile_static_opts -do_strip
|
$compile_cmd $compile_static_opts -do_strip
|
||||||
cp "$compile_result" "../$bintarget_static"
|
cp "$compile_result" "../$bintarget_static"
|
||||||
fi
|
fi
|
||||||
"$man_to_html_cmd"
|
|
||||||
mv "$man_page_html" ..
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Remove the build area
|
# Remove the build area
|
||||||
@ -222,5 +203,4 @@ rm -rf "$target"
|
|||||||
ls -l "$cdrskin_tarball"
|
ls -l "$cdrskin_tarball"
|
||||||
ls -l "$bintarget_dynamic"
|
ls -l "$bintarget_dynamic"
|
||||||
ls -l "$bintarget_static"
|
ls -l "$bintarget_static"
|
||||||
ls -l $(basename "$man_page_html")
|
|
||||||
|
|
@ -20,30 +20,26 @@ set -x
|
|||||||
# The script is to be run in the directory above the toplevel
|
# The script is to be run in the directory above the toplevel
|
||||||
# directory of libburn resp. cdrskin development.
|
# 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:
|
# Downloaded by:
|
||||||
# $ svn co http://libburnia-svn.pykix.org/libburn/tags/... $intermediate
|
# $ svn co http://libburn-svn.pykix.org/libburn/trunk libburn_pykix
|
||||||
# packed up in a tarball just to save it from inadverted changes by
|
# packed up in a tarball just to save it from inadverted changes by
|
||||||
# $ tar czf libburn_svn.tgz $intermediate
|
# $ tar czf libburn_svn.tgz libburn_pykix
|
||||||
original="./libburn_svn_release.tgz"
|
original="./libburn_svn.tgz"
|
||||||
# Historic moments:
|
# Historic moments:
|
||||||
# original="./libburn_svn_A60815.tgz"
|
# original="./libburn_svn_A60815.tgz"
|
||||||
# original="./libburn_cdrskin_A60819.tgz"
|
# original="./libburn_cdrskin_A60819.tgz"
|
||||||
|
|
||||||
|
# The top level directory in that snapshot is named
|
||||||
|
intermediate="./libburn_pykix"
|
||||||
|
|
||||||
# My changes are in $changes , mainly in $changes/cdrskin
|
# My changes are in libburn-0.2.3.ts.develop , mainly in ./cdrskin
|
||||||
changes="./libburn-release"
|
|
||||||
|
|
||||||
skin_release="0.3.2"
|
changes="./libburn-0.2.3.ts.develop"
|
||||||
patch_level=".pl00"
|
skin_rev="0.2.7"
|
||||||
skin_rev="$skin_release""$patch_level"
|
|
||||||
|
|
||||||
# The result directory and the name of the result tarballs
|
# The result directory and the name of the result tarballs
|
||||||
target="./cdrskin-${skin_release}"
|
target="./cdrskin-${skin_rev}"
|
||||||
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
|
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
|
||||||
cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz"
|
cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz"
|
||||||
|
|
||||||
@ -55,9 +51,6 @@ compile_cmd="./cdrskin/compile_cdrskin.sh"
|
|||||||
compile_static_opts="-static"
|
compile_static_opts="-static"
|
||||||
compile_result="cdrskin/cdrskin"
|
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_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
|
||||||
bintarget_static="$bintarget_dynamic"-static
|
bintarget_static="$bintarget_dynamic"-static
|
||||||
|
|
||||||
@ -126,8 +119,6 @@ do
|
|||||||
rm "$cdrskin_target"/cdrskin_"$i"
|
rm "$cdrskin_target"/cdrskin_"$i"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Remove eventual SVN stuff from cdrskin directory
|
|
||||||
for i in .deps .dirstamp .libs
|
for i in .deps .dirstamp .libs
|
||||||
do
|
do
|
||||||
if test -e "$cdrskin_target"/"$i"
|
if test -e "$cdrskin_target"/"$i"
|
||||||
@ -136,23 +127,6 @@ do
|
|||||||
fi
|
fi
|
||||||
done
|
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)
|
# Remove unwanted SVN stuff (TODO: avoid downloading it)
|
||||||
for i in "$target"/.svn "$target"/*/.svn
|
for i in "$target"/.svn "$target"/*/.svn
|
||||||
do
|
do
|
||||||
@ -167,6 +141,12 @@ do
|
|||||||
fi
|
fi
|
||||||
done
|
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
|
# Make SVN state tarball for the libburn team
|
||||||
tar czf "$cdrskin_tarball_svn" "$target"
|
tar czf "$cdrskin_tarball_svn" "$target"
|
||||||
@ -196,20 +176,18 @@ done
|
|||||||
# Pack it up to the new libburn+cdrskin-tarball
|
# Pack it up to the new libburn+cdrskin-tarball
|
||||||
tar czf "$cdrskin_tarball" "$target"
|
tar czf "$cdrskin_tarball" "$target"
|
||||||
|
|
||||||
# Produce a static and a dynamic binary, and a HTML man page
|
# Produce a static and a dynamic binary
|
||||||
(
|
(
|
||||||
cd "$compile_dir" || exit 1
|
cd "$compile_dir" || exit 1
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
"$compile_cmd" -do_strip
|
$compile_cmd -do_strip
|
||||||
cp "$compile_result" "../$bintarget_dynamic"
|
cp "$compile_result" "../$bintarget_dynamic"
|
||||||
if test -n "$compile_static_opts"
|
if test -n "$compile_static_opts"
|
||||||
then
|
then
|
||||||
"$compile_cmd" $compile_static_opts -do_strip
|
$compile_cmd $compile_static_opts -do_strip
|
||||||
cp "$compile_result" "../$bintarget_static"
|
cp "$compile_result" "../$bintarget_static"
|
||||||
fi
|
fi
|
||||||
"$man_to_html_cmd"
|
|
||||||
mv "$man_page_html" ..
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Remove the build area
|
# Remove the build area
|
||||||
@ -222,5 +200,4 @@ rm -rf "$target"
|
|||||||
ls -l "$cdrskin_tarball"
|
ls -l "$cdrskin_tarball"
|
||||||
ls -l "$bintarget_dynamic"
|
ls -l "$bintarget_dynamic"
|
||||||
ls -l "$bintarget_static"
|
ls -l "$bintarget_static"
|
||||||
ls -l $(basename "$man_page_html")
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.TH CDRSKIN 1 "February 8, 2007"
|
.TH CDRSKIN 1 "December 13, 2006"
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.\"
|
.\"
|
||||||
.\" Some roff macros, for reference:
|
.\" Some roff macros, for reference:
|
||||||
@ -16,8 +16,7 @@
|
|||||||
.\" .sp <n> insert n+1 empty lines
|
.\" .sp <n> insert n+1 empty lines
|
||||||
.\" for manpage-specific macros, see man(7)
|
.\" for manpage-specific macros, see man(7)
|
||||||
.SH NAME
|
.SH NAME
|
||||||
cdrskin \- burns preformatted data to CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW,
|
cdrskin \- burns preformatted data to CD-R or CD-RW via libburn.
|
||||||
DVD-RAM via libburn.
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B cdrskin
|
.B cdrskin
|
||||||
.RI [ options | track_source_addresses ]
|
.RI [ options | track_source_addresses ]
|
||||||
@ -28,47 +27,41 @@ DVD-RAM via libburn.
|
|||||||
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
|
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
|
||||||
.\" respectively.
|
.\" respectively.
|
||||||
.PP
|
.PP
|
||||||
\fBcdrskin\fP is a program that provides some of cdrecord's options
|
\fBcdrskin\fP is a program that provides some of cdrecord's options in a compatible way.
|
||||||
in a compatible way for CD media. With DVD it has its own ways.
|
You don't need to be root to use it.
|
||||||
You do not need to be superuser for its daily usage.
|
|
||||||
.PP
|
.PP
|
||||||
.B Overview of features:
|
.B Overview of features:
|
||||||
.br
|
.br
|
||||||
Blanking of CD-RW and DVD-RW.
|
Blanking of CD-RW.
|
||||||
.br
|
.br
|
||||||
Burning of data or audio tracks to CD,
|
Burning of data or audio tracks to CD.
|
||||||
.br
|
.br
|
||||||
either in versatile Track at Once mode (TAO)
|
Either in versatile Track at Once mode (TAO)
|
||||||
.br
|
.br
|
||||||
or in Session at Once mode for seamless tracks.
|
or in Session at Once mode for seamless tracks.
|
||||||
.br
|
.br
|
||||||
Multi session on CD (follow-up sessions in TAO only)
|
Multi session (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
|
.br
|
||||||
Bus scan, burnfree, speed options, retrieving media info, padding, fifo.
|
Bus scan, burnfree, speed options, retrieving media info, padding, fifo.
|
||||||
.br
|
.br
|
||||||
See section EXAMPLES at the end of this text.
|
See section EXAMPLES at the end of this text.
|
||||||
.PP
|
.PP
|
||||||
|
.B Known deficiencies:
|
||||||
|
.br
|
||||||
|
No DVD support yet.
|
||||||
|
.PP
|
||||||
.B Track recording model:
|
.B Track recording model:
|
||||||
.br
|
.br
|
||||||
The input-output entities which get processed are called tracks.
|
The input-output entities which get processed are called tracks.
|
||||||
A \fBtrack\fP stores a stream of bytes.
|
A track stores a stream of bytes.
|
||||||
.br
|
.br
|
||||||
Each track is initiated by one track source address argument, which may either
|
Each track is initiated by one track source address argument, which may either
|
||||||
be "-" for standard input or the address of a readable file. If no write mode
|
be "-" for standard input or the address of a readable file. If no write mode
|
||||||
is given explicitely then one will be chosen which matches the peculiarities
|
is given explicitely then one will be chosen which matches the peculiarities
|
||||||
of track sources and the state of the output media.
|
of track source and the state of the output media.
|
||||||
.PP
|
.PP
|
||||||
More than one track can be burned by a single run of cdrskin.
|
There can be more than one track burned by a single run of cdrskin.
|
||||||
In the terms of the MMC standard all tracks written by the same run constitute
|
CDs can be kept appendable so that further tracks can
|
||||||
a \fBsession\fP.
|
|
||||||
.br
|
|
||||||
Some media types can be kept appendable so that further tracks can
|
|
||||||
be written to them in subsequent runs of cdrskin (see option -multi).
|
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
|
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.
|
content (TOC) on media and can be retrieved via cdrskin option -toc.
|
||||||
@ -76,136 +69,36 @@ These informations are also used by the operating systems' CD-ROM read drivers.
|
|||||||
.PP
|
.PP
|
||||||
In general there are two types of tracks: data and audio. They differ in
|
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
|
sector size, throughput and readability via the systems' CD-ROM drivers
|
||||||
resp. by music CD players. With DVD there is only type data.
|
resp. by music CD players.
|
||||||
.br
|
.br
|
||||||
If not explicitely option -audio is given, then any track is burned as type
|
If not explicitely option -audio is given, then any track is burned as data
|
||||||
data, unless the track source is a file with suffix ".wav" or ".au" and has a
|
unless the track source is a file with suffix ".wav" or ".au" and has a
|
||||||
header part which identifies it as MS-WAVE resp. SUN Audio with suitable
|
header part which identifies it as MS-WAVE resp. SUN Audio with suitable
|
||||||
parameters. Such files are burned as audio tracks by default.
|
parameters. Such files are burned as audio tracks by default.
|
||||||
.PP
|
.PP
|
||||||
While audio tracks just contain a given time span of acoustic vibrations,
|
While audio tracks just contain a given time span of acoustic vibrations,
|
||||||
data tracks may have an arbitray meaning. Nevertheless, ISO-9660 filesystems
|
data tracks may have an arbitray meaning. Nevertheless, ISO-9660 filesystems
|
||||||
are established as a format which can represent a tree of directories and
|
are established as a format which can represent a tree of directories and
|
||||||
files on all major operating systems. Such filesystem images can be
|
data files on all major operating systems. Such filesystem images can be
|
||||||
produced by programs mkisofs or genisoimage. They can also be extended by
|
produced by programs mkisofs or genisoimage. They can also be extended by
|
||||||
follow-up tracks if prepared properly. See the man pages of said programs.
|
follow-up tracks if prepared properly. See the man pages of said programs.
|
||||||
cdrskin is able to fulfill the needs about their option -C.
|
cdrskin is able to fulfill the needs about their option -C.
|
||||||
.br
|
.br
|
||||||
Another type of data track content are archive formats which originally
|
Another type of data track content are archive formats which originally
|
||||||
have been developed for magnetic tapes. Only formats which mark a detectable
|
have been developed for magnetic tapes. Only formats which mark a detectable
|
||||||
end-of-archive in their data are suitable, though. Well tested are
|
end-of-archive in their data are suitable with CD, though. Well tested are
|
||||||
the archivers afio and star. Not suitable seems GNU tar.
|
the archivers afio and star. Not suitable seems GNU tar.
|
||||||
.PP
|
.PP
|
||||||
.B Recordable CD Media:
|
.B Recordable CD Media:
|
||||||
.br
|
.br
|
||||||
CD-R can be initially written only once and eventually extended until they
|
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
|
get closed (or are spoiled because they are overly full). After that they are
|
||||||
read-only. Closing is done automatically unless option
|
read-only.
|
||||||
.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
|
.br
|
||||||
CD-RW media can be blanked to make them re-usable for another
|
CD-RW media can be blanked to make them re-usable for another
|
||||||
round of overwriting. Usually
|
round of overwriting. Blanking damages the previous content but does not
|
||||||
.B blank=fast
|
|
||||||
is the appropriate option.
|
|
||||||
Blanking damages the previous content but does not
|
|
||||||
make it completely unreadable. It is no effective privacy precaution.
|
make it completely unreadable. It is no effective privacy precaution.
|
||||||
Multiple cycles of blanking and overwriting with random numbers might be.
|
Multiple cycles of blanking and overwriting with random numbers might be.
|
||||||
.PP
|
|
||||||
.B Sequentially Recordable DVD Media:
|
|
||||||
.br
|
|
||||||
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.
|
|
||||||
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 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
|
|
||||||
The drives, either CD burners or DVD burners, are accessed via addresses which
|
|
||||||
are specific to libburn and the operating system. Those addresses get listed
|
|
||||||
by a run of \fBcdrskin --devices\fP.
|
|
||||||
.br
|
|
||||||
On Linux, they are device files which traditionally do not offer
|
|
||||||
w-permissions for normal users. Because libburn needs rw-permission,
|
|
||||||
it might be only the superuser who is able to get this list without further
|
|
||||||
precautions.
|
|
||||||
.br
|
|
||||||
It is consensus that \fBchmod a+rw /dev/sg0\fP or \fBchmod a+rw /dev/hdc\fP
|
|
||||||
is less security sensitive than chmod u+s /usr/bin/cdrskin. The risk for the
|
|
||||||
drive is somewhat higher but the overall system is much less at stake.
|
|
||||||
.br
|
|
||||||
.PP
|
|
||||||
If you only got one CD capable drive then you may leave out cdrskin option
|
|
||||||
\fBdev=\fP. Else you should use this option to address the drive you want.
|
|
||||||
.br
|
|
||||||
cdrskin option dev= not only accepts the listed addresses but also
|
|
||||||
traditional cdrecord SCSI addresses which on Linux consist of three
|
|
||||||
numbers: Bus,Target,Lun. There is also a related address family "ATA" which
|
|
||||||
accesses IDE drives not under control of Linux SCSI drivers:
|
|
||||||
ATA:Bus,Target,Lun.
|
|
||||||
.br
|
|
||||||
See option -scanbus for getting a list of cdrecord style addresses.
|
|
||||||
.br
|
|
||||||
Further are accepted on Linux: links to libburn-suitable device files,
|
|
||||||
device files which have the same major and minor device number,
|
|
||||||
and device files which have the same SCSI address parameters (e.g. /dev/sr0).
|
|
||||||
.br
|
.br
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
@ -224,22 +117,17 @@ original cdrecord by Joerg Schilling:
|
|||||||
.TP
|
.TP
|
||||||
.BI \-atip
|
.BI \-atip
|
||||||
Retrieve some info about media state. With CD-RW print "Is erasable".
|
Retrieve some info about media state. With CD-RW print "Is erasable".
|
||||||
With DVD media print "book type:" and a media type text.
|
|
||||||
.TP
|
.TP
|
||||||
.BI \-audio
|
.BI \-audio
|
||||||
Announces that the subsequent tracks are to be burned as audio.
|
Announces that the subsequent tracks are to be burned as audio.
|
||||||
The source is supposed to be uncompressed headerless PCM, 44100 Hz, 16 bit,
|
The source is supposed to be uncompressed headerless PCM, 44100 Hz, 16 bit,
|
||||||
stereo. For little-endian byte order (which is usual on PCs) use option
|
stereo. For little-endian byte order (which is usual on PCs) use option
|
||||||
-swab. Unless marked explicitely by option -data, input files with suffix
|
-swab. Input files with suffix .wav are examined wether they have a header
|
||||||
.wav are examined wether they have a header in MS-WAVE format confirming
|
in MS-WAVE format confirming those parameters and eventually raw audio data
|
||||||
those parameters and eventually raw audio data get extracted and burned as
|
get extracted automatically. Same is done for suffix .au and SUN Audio.
|
||||||
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
|
.TP
|
||||||
.BI blank= type
|
.BI blank= type
|
||||||
Blank a CD-RW, a DVD-RW, or format a DVD+/-RW.
|
Blank a CD-RW disc. This is combinable with burning in the same run of cdrskin.
|
||||||
This is combinable with burning in the same run of cdrskin.
|
|
||||||
The type given with blank= selects the particular behavior:
|
The type given with blank= selects the particular behavior:
|
||||||
.RS
|
.RS
|
||||||
.TP
|
.TP
|
||||||
@ -247,45 +135,10 @@ help
|
|||||||
Print this list of blanking types.
|
Print this list of blanking types.
|
||||||
.TP
|
.TP
|
||||||
all
|
all
|
||||||
Blank an entire CD-RW or an unformatted DVD-RW.
|
Blank the entire disk.
|
||||||
(See also --prodvd_cli_compatible)
|
|
||||||
.TP
|
.TP
|
||||||
fast
|
fast
|
||||||
Minimally blank an entire CD-RW or blank an unformatted DVD-RW.
|
Minimally blank the entire disk.
|
||||||
(See also --prodvd_cli_compatible)
|
|
||||||
.TP
|
|
||||||
format_overwrite
|
|
||||||
Format a DVD-RW to "Restricted Overwrite". The user should bring some patience.
|
|
||||||
.br
|
|
||||||
(Note: blank=format_overwrite* are not original cdrecord options.)
|
|
||||||
.TP
|
|
||||||
format_overwrite_quickest
|
|
||||||
Like format_overwrite without creating a 128 MB trailblazer session.
|
|
||||||
Leads to "intermediate" state which only allows sequential write
|
|
||||||
beginning from address 0.
|
|
||||||
The "intermediate" state ends after the first session of writing data.
|
|
||||||
.TP
|
|
||||||
format_overwrite_full
|
|
||||||
For DVD-RW this is like format_overwrite but claims full media size
|
|
||||||
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
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.BI \-checkdrive
|
.BI \-checkdrive
|
||||||
@ -293,42 +146,38 @@ Retrieve some info about the addressed drive.
|
|||||||
Exits with non-zero value if the drive cannot be found and opened.
|
Exits with non-zero value if the drive cannot be found and opened.
|
||||||
.TP
|
.TP
|
||||||
.BI \-dao
|
.BI \-dao
|
||||||
Alias for option -sao. Write CD in Session at Once mode
|
Alias for option -sao. Write disk in Session at Once mode.
|
||||||
or DVD-R[W] in Disc-at-once mode.
|
|
||||||
.TP
|
.TP
|
||||||
.BI \-data
|
.BI \-data
|
||||||
Subsequent tracks are data tracks. This option is default and only needed
|
Subsequent tracks are data tracks. This option is default and only needed
|
||||||
to mark the end of the range of an eventual option -audio.
|
to mark the end of the range of an eventual option -audio.
|
||||||
.TP
|
.TP
|
||||||
.BI dev= target
|
.BI dev= target
|
||||||
Set the address of the drive to use. Valid are at least the
|
Sets the (pseudo-)SCSI address of the drive to use. Valid are at least the
|
||||||
addresses listed with option --devices,
|
X,Y,Z addresses listed with option -scanbus, ATA:X,Y,Z addresses listed with
|
||||||
X,Y,Z addresses listed with option -scanbus,
|
options dev=ATA -scanbus, the device file addresses listed with
|
||||||
ATA:X,Y,Z addresses listed with options dev=ATA -scanbus,
|
option --devices , volatile libburn drive numbers (numbering starts at "0").
|
||||||
and volatile libburn drive numbers (numbering starts at "0").
|
|
||||||
Other device file addresses which lead to the same drive might work too.
|
Other device file addresses which lead to the same drive might work too.
|
||||||
.br
|
.br
|
||||||
If no dev= is given, volatile address "dev=0" is assumed. That is the first
|
If no dev= is given, volatile address "dev=0" is assumed. That is the first
|
||||||
drive found being available. Better avoid this ambiguity on systems with more
|
drive found being available. Better avoid this on multi-drive systems.
|
||||||
than one drive.
|
|
||||||
.br
|
.br
|
||||||
The special target "help" lists hints about available addressing formats.
|
The special target "help" lists hints about available addressing formats.
|
||||||
Be aware that deprecated option --old_pseudo_scsi_adr may change the meaning
|
Be aware that option --old_pseudo_scsi_adr changes the meaning of
|
||||||
of Bus,Target,Lun addresses.
|
Bus,Target,Lun addresses.
|
||||||
.TP
|
.TP
|
||||||
.BI driveropts= opt
|
.BI driveropts= opt
|
||||||
Set "driveropts=noburnfree" to disable the drive's eventual protection
|
Set "driveropts=burnfree" to enable the drive's eventual protection mechanism
|
||||||
mechanism against temporary lack of source data (i.e. buffer underrun).
|
against temporary lack of source data (i.e. buffer underrun).
|
||||||
A drive that announces no such capabilities will not get them enabled anyway,
|
It is not an error to do this with a drive that has no such capabilities.
|
||||||
even if attempted explicitely via "driveropts=burnfree".
|
|
||||||
.TP
|
.TP
|
||||||
.BI \-dummy
|
.BI \-dummy
|
||||||
Try to perform the drive operations without actually affecting the inserted
|
Try to perform the drive operations without actually affecting the inserted
|
||||||
media. There is no guarantee that this will work with a particular combination
|
media. There is no guarantee that this will work with a particular drive
|
||||||
of drive, media, and write mode. Blanking is prevented reliably, though.
|
in a particular write mode. Blanking is prevented reliably, though.
|
||||||
.TP
|
.TP
|
||||||
.BI \-eject
|
.BI \-eject
|
||||||
Eject the disc after work is done.
|
Eject the disk after work is done.
|
||||||
.TP
|
.TP
|
||||||
.BI \-force
|
.BI \-force
|
||||||
Assume that the user knows better in situations when cdrskin or libburn are
|
Assume that the user knows better in situations when cdrskin or libburn are
|
||||||
@ -336,9 +185,6 @@ insecure about drive or media state. This includes the attempt to blank
|
|||||||
media which are classified as unknown or unsuitable, and the attempt to use
|
media which are classified as unknown or unsuitable, and the attempt to use
|
||||||
write modes which libburn believes they are not supported by the drive.
|
write modes which libburn believes they are not supported by the drive.
|
||||||
.br
|
.br
|
||||||
Another application is with blank=format_* to enforce re-formatting of media
|
|
||||||
which appear to be sufficiently formatted already.
|
|
||||||
.br
|
|
||||||
Use this only when in urgent need.
|
Use this only when in urgent need.
|
||||||
.TP
|
.TP
|
||||||
.BI fs= size
|
.BI fs= size
|
||||||
@ -360,13 +206,6 @@ option fifo_start_at=size.
|
|||||||
.BI gracetime= seconds
|
.BI gracetime= seconds
|
||||||
Set the grace time before starting to write. (Default is 0)
|
Set the grace time before starting to write. (Default is 0)
|
||||||
.TP
|
.TP
|
||||||
.BI msifile= path
|
|
||||||
Run option -msinfo and copy the result line into the file given by path.
|
|
||||||
Unlike -msinfo this option does not redirect all normal output away from
|
|
||||||
standard output. But it may be combined with -msinfo to achieve this.
|
|
||||||
.br
|
|
||||||
Note: msifile=path is actually an option of wodim and not of cdrecord.
|
|
||||||
.TP
|
|
||||||
.BI \-msinfo
|
.BI \-msinfo
|
||||||
Retrieve multi-session info for preparing a follow-up session by option -C
|
Retrieve multi-session info for preparing a follow-up session by option -C
|
||||||
of programs mkisofs or genisoimage. Print result to standard output.
|
of programs mkisofs or genisoimage. Print result to standard output.
|
||||||
@ -378,15 +217,11 @@ start address of the next session to be appended. The string is empty if
|
|||||||
the most recent session was not written with option -multi.
|
the most recent session was not written with option -multi.
|
||||||
.TP
|
.TP
|
||||||
.BI \-multi
|
.BI \-multi
|
||||||
This option keeps the CD or unformatted DVD-R[W] appendable after the current
|
This option keeps the CD appendable after the current session has been written.
|
||||||
session has been written.
|
Without it the disk gets closed and may not be written any more - unless it
|
||||||
Without it the disc gets closed and may not be written any more - unless it
|
is a CD-RW and gets blanked which causes loss of its content.
|
||||||
is a -RW and gets blanked which causes loss of its content.
|
|
||||||
.br
|
.br
|
||||||
The following sessions can only be written in -tao mode. -multi is prohibited
|
The following sessions can only be written in -tao mode.
|
||||||
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
|
.br
|
||||||
In order to have all filesystem content accessible, the eventual ISO-9660
|
In order to have all filesystem content accessible, the eventual ISO-9660
|
||||||
filesystem of a follow-up
|
filesystem of a follow-up
|
||||||
@ -412,27 +247,18 @@ 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=.
|
again before the next track argument. About size specifiers, see option fs=.
|
||||||
.TP
|
.TP
|
||||||
.BI \-raw96r
|
.BI \-raw96r
|
||||||
Write CD in RAW/RAW96R mode. This mode allows to put more payload bytes
|
Write disk 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
|
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
|
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.
|
then behave strange or even go bad for the next few attempts to burn a CD.
|
||||||
One should use it only if inavoidable.
|
One should use it only if inavoidable.
|
||||||
.TP
|
.TP
|
||||||
.BI \-sao
|
.BI \-sao
|
||||||
Write CD in Session At Once mode, resp. a sequential DVD-R[W] in Disc-at-once
|
Write disk in Session At Once mode. This mode is able to put several audio
|
||||||
(DAO) mode.
|
tracks on CD without producing audible gaps between them. It can only
|
||||||
.br
|
be used for tracks of fixely predicted size. This implies that track arguments
|
||||||
With CD this mode is able to put several audio tracks on media without
|
which depict stdin or named pipes need to be preceeded by option tsize= or
|
||||||
producing audible gaps between them.
|
by option tao_to_sao_tsize=.
|
||||||
.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
|
.TP
|
||||||
.BI \-scanbus
|
.BI \-scanbus
|
||||||
Scan the system for drives. On Linux the drives at /dev/s* and at /dev/hd*
|
Scan the system for drives. On Linux the drives at /dev/s* and at /dev/hd*
|
||||||
@ -449,8 +275,7 @@ Bus,Target,Lun Number) 'Vendor' 'Mode' 'Revision'
|
|||||||
.TP
|
.TP
|
||||||
.BI speed= number
|
.BI speed= number
|
||||||
Set speed of drive. With data CD, 1x speed corresponds to a throughput of
|
Set speed of drive. With data CD, 1x speed corresponds to a throughput of
|
||||||
150,000 bytes/second. With DVD, 1x = 1,385,000 bytes/second.
|
150 kB/s. It is not an error to set a speed higher than is suitable for drive
|
||||||
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.
|
and media. One should stay within a realistic speed range, though.
|
||||||
.TP
|
.TP
|
||||||
.BI \-swab
|
.BI \-swab
|
||||||
@ -462,20 +287,17 @@ Less guesswork is needed if track sources are in format MS-WAVE in a file with
|
|||||||
suffix ".wav".
|
suffix ".wav".
|
||||||
.TP
|
.TP
|
||||||
.BI \-tao
|
.BI \-tao
|
||||||
Write CD in Track At Once (TAO) mode, resp. sequential DVD-R[W] in Incremental
|
Write disk in Track At Once (TAO) mode. This mode can be used with track
|
||||||
Streaming mode. This mode also applies pro-forma to overwriteable DVD media.
|
sources of unpredictable size, like standard input or named pipes. It is
|
||||||
.br
|
also the only mode that can be used for writing to appendable CD which
|
||||||
Mode -tao can be used with track sources of unpredictable size, like standard
|
already hold data.
|
||||||
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
|
.TP
|
||||||
.BI \-toc
|
.BI \-toc
|
||||||
Print the table of content (TOC) which describes the tracks recorded on disc.
|
Print the table of content (TOC) which describes the tracks recorded on CD.
|
||||||
The output contains all info from option -atip plus lines which begin with
|
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
|
"track: " followed by the track number, the word "lba:" and a number which
|
||||||
start address of the track. Addresses are counted in CD sectors which with
|
gives the start address of the track. Addresses are counted in CD sectors which
|
||||||
SAO or TAO data tracks hold 2048 bytes each.
|
with data tracks hold 2048 bytes each.
|
||||||
.RS
|
.RS
|
||||||
.TP
|
.TP
|
||||||
Example. Retrieve an afio archive from track number 2:
|
Example. Retrieve an afio archive from track number 2:
|
||||||
@ -484,7 +306,7 @@ tracknumber=2
|
|||||||
.br
|
.br
|
||||||
lba=$(cdrskin dev=/dev/cdrom -toc 2>&1 | \\
|
lba=$(cdrskin dev=/dev/cdrom -toc 2>&1 | \\
|
||||||
.br
|
.br
|
||||||
grep '^track:[ ]*[ 0-9][0-9]' | \\
|
grep '^track: [ 0-9][0-9]' | \\
|
||||||
.br
|
.br
|
||||||
tail +"$tracknumber" | head -1 | \\
|
tail +"$tracknumber" | head -1 | \\
|
||||||
.br
|
.br
|
||||||
@ -504,7 +326,7 @@ About size specifiers, see option fs=.
|
|||||||
If the track source does not deliver the predicted amount of bytes, the
|
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.
|
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
|
If on the other hand the track source delivers more than the announced bytes
|
||||||
then the track on media gets truncated to the predicted size and cdrskin exits
|
then the track on CD gets truncated to the predicted size and cdrskin exits
|
||||||
with non-zero value.
|
with non-zero value.
|
||||||
.TP
|
.TP
|
||||||
.BI \-v
|
.BI \-v
|
||||||
@ -519,7 +341,8 @@ Alphabetical list of options which are genuine to cdrskin and intended for
|
|||||||
normal use:
|
normal use:
|
||||||
.TP
|
.TP
|
||||||
.BI \--allow_setuid
|
.BI \--allow_setuid
|
||||||
Disable the loud warning about insecure discrepance between login user and
|
Disable the program abort triggered by an insecure discrepance between
|
||||||
|
login user and
|
||||||
effective user which indicates application of chmod u+s to the program binary.
|
effective user which indicates application of chmod u+s to the program binary.
|
||||||
One should not do this chmod u+s , but it is an old cdrecord tradition.
|
One should not do this chmod u+s , but it is an old cdrecord tradition.
|
||||||
.TP
|
.TP
|
||||||
@ -527,16 +350,16 @@ One should not do this chmod u+s , but it is an old cdrecord tradition.
|
|||||||
Allow source_addresses to begin with "-" (plus further characters) or to
|
Allow source_addresses to begin with "-" (plus further characters) or to
|
||||||
contain a "=" character.
|
contain a "=" character.
|
||||||
By default such arguments are seen as misspelled options. It is nevertheless
|
By default such arguments are seen as misspelled options. It is nevertheless
|
||||||
not possible to use one of the options listed with --list_ignored_options.
|
not possible to use one of the options of cdrecord-2.01.
|
||||||
.TP
|
.TP
|
||||||
.BI \--demand_a_drive
|
.BI \--demand_a_drive
|
||||||
Exit with a nonzero value if no drive can be found during a bus scan.
|
Exit with a nonzero value if no drive can be found during a bus scan.
|
||||||
.TP
|
.TP
|
||||||
.BI \--devices
|
.BI \--devices
|
||||||
List the device file addresses of all accessible CD drives. In order to get
|
List the device file addresses of all accessible drives. In order to get
|
||||||
listed, a drive has to offer rw-permission for the cdrskin user and it may
|
listed a drive has to offer rw-permission for the cdrskin user and it may
|
||||||
not be busy. The superuser should be able to see all idle drives listed and
|
not be busy.
|
||||||
busy drives reported as "SORRY" messages.
|
Busy drives are reported as "SORRY" messages on standard error.
|
||||||
.br
|
.br
|
||||||
Each available drive gets listed by a line containing the following fields:
|
Each available drive gets listed by a line containing the following fields:
|
||||||
.br
|
.br
|
||||||
@ -544,6 +367,10 @@ Number dev='Devicefile' rw-Permissions : 'Vendor' 'Model'
|
|||||||
.br
|
.br
|
||||||
Number and Devicefile can both be used with option dev=, but number is
|
Number and Devicefile can both be used with option dev=, but number is
|
||||||
volatile (numbering changes if drives become busy).
|
volatile (numbering changes if drives become busy).
|
||||||
|
Normal users might not see all drives unless the superuser enabled access
|
||||||
|
by chmod o+rw
|
||||||
|
after using cdrskin --devices to get an overview of the situation.
|
||||||
|
That's why current rw-Permissions are listed.
|
||||||
.TP
|
.TP
|
||||||
.BI fifo_start_at= size
|
.BI fifo_start_at= size
|
||||||
Do not wait for full fifo but start burning as soon as the given number
|
Do not wait for full fifo but start burning as soon as the given number
|
||||||
@ -553,50 +380,14 @@ 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,
|
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
|
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
|
fifo_start_at= . So it is best if the drive offers hardware protection which
|
||||||
is enabled automatically if not driveropts=noburnfree is given.
|
has to be enabled by driveropts=burnfree.
|
||||||
.TP
|
|
||||||
.BI \--list_ignored_options
|
|
||||||
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
|
.TP
|
||||||
.BI \--no_rc
|
.BI \--no_rc
|
||||||
Only if used as first command line argument this option prevents reading and
|
Only if used as first command line argument this option prevents reading and
|
||||||
interpretation of eventual startup files. See section FILES below.
|
interpretation of eventual startup files. See section FILES below.
|
||||||
.TP
|
.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
|
.BI \--single_track
|
||||||
Accept only the last argument of the command line as track source address.
|
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
|
|
||||||
DVD-RAM byte_offset must be aligned to 2 KB blocks, but better is 32 kB.
|
|
||||||
With DVD-RW 32 kB alignment is mandatory.
|
|
||||||
.br
|
|
||||||
Other media are not suitable for this option yet.
|
|
||||||
.PP
|
.PP
|
||||||
Alphabetical list of options which are only intended for very special
|
Alphabetical list of options which are only intended for very special
|
||||||
situations and not for normal use:
|
situations and not for normal use:
|
||||||
@ -659,8 +450,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.
|
idea. You might end up with a stuck drive that refuses to hand out the media.
|
||||||
.TP
|
.TP
|
||||||
.BI \--no_blank_appendable
|
.BI \--no_blank_appendable
|
||||||
Refuse to blank appendable CD-RW or DVD-RW. This is a feature that was once
|
Refuse to blank appendable CD-RW. This is a feature that was once builtin with
|
||||||
builtin with libburn. No information available for what use case it was needed.
|
libburn. No information available for what use case it was needed.
|
||||||
.TP
|
.TP
|
||||||
.BI \--no_convert_fs_adr
|
.BI \--no_convert_fs_adr
|
||||||
Do only literal translations of dev=. This prevents cdrskin from test-opening
|
Do only literal translations of dev=. This prevents cdrskin from test-opening
|
||||||
@ -677,10 +468,16 @@ Linux specific:
|
|||||||
Use and report literal Bus,Target,Lun addresses rather than real SCSI and
|
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
|
pseudo ATA addresses. This method is outdated and was never compatible with
|
||||||
original cdrecord.
|
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
|
.br
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.SS
|
.SS
|
||||||
.B Get an overview of drives and their addresses:
|
.B Get an overview of drives:
|
||||||
.br
|
.br
|
||||||
cdrskin -scanbus
|
cdrskin -scanbus
|
||||||
.br
|
.br
|
||||||
@ -692,57 +489,53 @@ cdrskin --devices
|
|||||||
.br
|
.br
|
||||||
cdrskin dev=0,1,0 -checkdrive
|
cdrskin dev=0,1,0 -checkdrive
|
||||||
.br
|
.br
|
||||||
cdrskin dev=ATA:1,0,0 -v -atip
|
cdrskin dev=ATA:1,0,0 -atip
|
||||||
.br
|
.br
|
||||||
cdrskin dev=/dev/hdc -toc
|
cdrskin dev=/dev/hdc -toc
|
||||||
.SS
|
.SS
|
||||||
.B Make used CD-RW or used unformatted DVD-RW writable again:
|
.B Make used CD-RW writable again:
|
||||||
.br
|
.br
|
||||||
cdrskin -v dev=/dev/sg1 blank=fast -eject
|
cdrskin -v dev=/dev/sg1 blank=all -eject
|
||||||
.br
|
.br
|
||||||
cdrskin -v dev=/dev/dvd blank=all -eject
|
cdrskin -v dev=/dev/dvd blank=fast -eject
|
||||||
.SS
|
.SS
|
||||||
.B Format DVD-RW to avoid need for blanking before re-use:
|
.B Write ISO-9660 filesystem image:
|
||||||
.br
|
|
||||||
cdrskin -v dev=/dev/sr0 blank=format_overwrite
|
|
||||||
.SS
|
|
||||||
.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
|
.br
|
||||||
cdrskin -v dev=/dev/hdc speed=12 fs=8m \\
|
cdrskin -v dev=/dev/hdc speed=12 fs=8m \\
|
||||||
.br
|
.br
|
||||||
-sao -eject padsize=300k my_image.iso
|
driveropts=burnfree -sao -eject \\
|
||||||
|
.br
|
||||||
|
padsize=300k my_image.iso
|
||||||
.SS
|
.SS
|
||||||
.B Write compressed afio archive on-the-fly:
|
.B Write compressed afio archive on-the-fly:
|
||||||
.br
|
.br
|
||||||
find . | afio -oZ - | \\
|
find . | afio -oZ - | \\
|
||||||
.br
|
.br
|
||||||
cdrskin -v dev=0,1,0 fs=32m speed=8 \\
|
cdrskin -v dev=0,1,0 fs=32m speed=8 driveropts=burnfree \\
|
||||||
.br
|
.br
|
||||||
-tao padsize=300k -
|
padsize=300k -tao -
|
||||||
.SS
|
.SS
|
||||||
.B Write several sessions to the same CD or DVD-R[W]:
|
.B Write several sessions to the same CD:
|
||||||
.br
|
.br
|
||||||
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso
|
cdrskin dev=/dev/hdc padsize=300k -multi 1.iso
|
||||||
.br
|
.br
|
||||||
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso
|
cdrskin dev=/dev/hdc padsize=300k -multi -tao 2.afio
|
||||||
.br
|
.br
|
||||||
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso
|
cdrskin dev=/dev/hdc padsize=300k -multi -tao 3.afio
|
||||||
.br
|
.br
|
||||||
cdrskin dev=/dev/hdc -v padsize=300k -tao 4.iso
|
cdrskin dev=/dev/hdc padsize=300k -tao 4.afio
|
||||||
.SS
|
.SS
|
||||||
.B Get CD or DVD-R[W] multi-session info for option -C of program mkisofs:
|
.B Get the multi-session info for option -C of program mkisofs:
|
||||||
.br
|
.br
|
||||||
c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)
|
c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)
|
||||||
.br
|
.br
|
||||||
mkisofs ... -C "$c_values" ...
|
mkisofs ... -C "$c_values" ...
|
||||||
.SS
|
.SS
|
||||||
.B Write audio tracks to CD:
|
.B Write audio tracks:
|
||||||
.br
|
.br
|
||||||
cdrskin -v dev=ATA:1,0,0 speed=48 -sao \\
|
cdrskin -v dev=ATA:1,0,0 speed=48 \\
|
||||||
|
.br
|
||||||
|
driveropts=burnfree -sao \\
|
||||||
.br
|
.br
|
||||||
track1.wav track2.au -audio -swab track3.raw
|
track1.wav track2.au -audio -swab track3.raw
|
||||||
.br
|
.br
|
||||||
@ -755,8 +548,6 @@ startup to read the arguments from the following files:
|
|||||||
.br
|
.br
|
||||||
.B /etc/opt/cdrskin/rc
|
.B /etc/opt/cdrskin/rc
|
||||||
.br
|
.br
|
||||||
.B /etc/cdrskin/cdrskin.conf
|
|
||||||
.br
|
|
||||||
.B $HOME/.cdrskinrc
|
.B $HOME/.cdrskinrc
|
||||||
.br
|
.br
|
||||||
.PP
|
.PP
|
||||||
@ -791,13 +582,13 @@ Formatting track sources for cdrskin:
|
|||||||
.BR star (1)
|
.BR star (1)
|
||||||
.br
|
.br
|
||||||
.TP
|
.TP
|
||||||
Other CD/DVD burn programs:
|
Other CD burn programs:
|
||||||
.br
|
.br
|
||||||
.BR cdrecord (1),
|
.BR cdrecord (1),
|
||||||
.BR wodim (1)
|
.BR wodim (1)
|
||||||
.br
|
.br
|
||||||
.TP
|
.TP
|
||||||
For DVD burning (also tutor of libburn's DVD capabilities):
|
For DVD burning:
|
||||||
.br
|
.br
|
||||||
.BR growisofs (1)
|
.BR growisofs (1)
|
||||||
.br
|
.br
|
||||||
|
1044
cdrskin/cdrskin.c
1044
cdrskin/cdrskin.c
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<HEAD>
|
<HEAD>
|
||||||
<META NAME="description" CONTENT="cdrskin, a limited cdrecord compatibility wrapper for libburn">
|
<META NAME="description" CONTENT="cdrskin, a limited cdrecord compatibility wrapper for libburn">
|
||||||
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, linux, CDR, CD-R, CDRW, CD-RW, cdrecord, compatible, scdbackup, burning">
|
<META NAME="keywords" CONTENT="cdrskin, libburn, burn, CD, linux, CDR, CD-R, CDRW, CD-RW, cdrecord, compatible, scdbackup, burning">
|
||||||
<META NAME="robots" CONTENT="follow">
|
<META NAME="robots" CONTENT="follow">
|
||||||
<TITLE>cdrskin homepage english</TITLE>
|
<TITLE>cdrskin homepage english</TITLE>
|
||||||
</HEAD>
|
</HEAD>
|
||||||
@ -11,12 +11,7 @@
|
|||||||
<FONT SIZE=+1>
|
<FONT SIZE=+1>
|
||||||
|
|
||||||
<CENTER>
|
<CENTER>
|
||||||
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
<P><H2>Homepage of</H2><H1><BR>cdrskin</H1><BR>
|
||||||
<IMG SRC="doener_150x200_tr_octx.gif" BORDER=0
|
|
||||||
ALT="cdrskin logo: Doener mit Scharf">
|
|
||||||
</A>
|
|
||||||
<P><H2> Homepage of </H2>
|
|
||||||
<H1> cdrskin </H1>
|
|
||||||
<!-- <FONT SIZE=+0><A HREF="cdrskin_ger.html">deutsch (german)</A></FONT> -->
|
<!-- <FONT SIZE=+0><A HREF="cdrskin_ger.html">deutsch (german)</A></FONT> -->
|
||||||
|
|
||||||
<H2>Limited cdrecord compatibility wrapper for libburn</H2>
|
<H2>Limited cdrecord compatibility wrapper for libburn</H2>
|
||||||
@ -25,7 +20,7 @@
|
|||||||
<P>
|
<P>
|
||||||
<H2>Purpose:</H2>
|
<H2>Purpose:</H2>
|
||||||
<UL>
|
<UL>
|
||||||
<LI>Burns preformatted data to CD-R, CD-RW, DVD-R, DVD-RW, DVD-RAM, DVD+RW</LI>
|
<LI>Burns preformatted data to CD-R or CD-RW</LI>
|
||||||
</UL>
|
</UL>
|
||||||
</P>
|
</P>
|
||||||
<P>
|
<P>
|
||||||
@ -34,9 +29,9 @@
|
|||||||
|
|
||||||
<P>
|
<P>
|
||||||
<H2>Hardware requirements:</H2>
|
<H2>Hardware requirements:</H2>
|
||||||
A CD/DVD recorder suitable for
|
A CD recorder suitable for
|
||||||
<A HREF="http://libburnia.pykix.org">libburnia.pykix.org</A>
|
<A HREF="http://libburn.pykix.org">libburn.pykix.org</A>
|
||||||
(SCSI or IDE/ATAPI writers compliant to standard MMC-3 or higher).
|
(SCSI or IDE/ATAPI writers compliant to mmc standard).
|
||||||
<BR>
|
<BR>
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
@ -56,8 +51,8 @@ A CD/DVD recorder suitable for
|
|||||||
GPL software included:<BR>
|
GPL software included:<BR>
|
||||||
</H2>
|
</H2>
|
||||||
<DL>
|
<DL>
|
||||||
<DT>libburn-0.3.2</DT>
|
<DT>libburn-0.2.6</DT>
|
||||||
<DD>(by Derek Foreman, Ben Jansens, and team of libburnia.pykix.org)</DD>
|
<DD>(by Derek Foreman, Ben Jansens, and team of libburn.pykix.org)</DD>
|
||||||
<DD>transfers data to CD</DD>
|
<DD>transfers data to CD</DD>
|
||||||
</DL>
|
</DL>
|
||||||
</P>
|
</P>
|
||||||
@ -88,75 +83,35 @@ and for data CD projects of <A HREF="http://www.k3b.org">K3b</A>
|
|||||||
(see <A HREF="#examples">examples</A>).
|
(see <A HREF="#examples">examples</A>).
|
||||||
Suitability for audio CD frontends has been improved much and is now being
|
Suitability for audio CD frontends has been improved much and is now being
|
||||||
evaluated.<BR>
|
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
|
Further enhancements depend on people who can describe and discuss their
|
||||||
wishes as well as on the development of libburn.</DT>
|
wishes as well as on the development of libburn.</DT>
|
||||||
<BR><BR>
|
<BR><BR>
|
||||||
<DT>Get an overview of drives and their addresses:</DT>
|
<DT>Get an overview of drives:</DT>
|
||||||
<DD>$<KBD> cdrskin -scanbus</KBD></DD>
|
<DD>$ cdrskin -scanbus</DD>
|
||||||
<DD>$<KBD> cdrskin dev=ATA -scanbus</KBD></DD>
|
<DD>$ cdrskin dev=ATA -scanbus</DD>
|
||||||
<DD>$<KBD> cdrskin --devices</KBD></DD>
|
<DD>$ cdrskin --devices</DD>
|
||||||
|
|
||||||
<DT>Get info about a particular drive or loaded media:</DT>
|
<DT>Get info about a particular drive or loaded media:</DT>
|
||||||
<DD>$<KBD> cdrskin dev=0,1,0 -checkdrive</KBD></DD>
|
<DD>$ cdrskin dev=0,1,0 -checkdrive</DD>
|
||||||
<DD>$<KBD> cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
|
<DD>$ cdrskin dev=ATA:1,0,0 -atip</DD>
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -toc</KBD></DD>
|
<DD>$ cdrskin dev=/dev/hdc -toc</DD>
|
||||||
|
<DT>Make used CD-RW writable again:</DT>
|
||||||
<DT>Make used CD-RW or used unformatted DVD-RW writable again:</DT>
|
<DD>$ cdrskin -v dev=/dev/sg1 blank=all -eject</DD>
|
||||||
<DD>$<KBD> cdrskin -v dev=/dev/sg1 blank=fast -eject</KBD></DD>
|
<DD>$ cdrskin -v dev=/dev/dvd blank=fast -eject</DD>
|
||||||
<DD>$<KBD> cdrskin -v dev=/dev/dvd blank=all -eject</KBD></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>Format DVD-RW to avoid need for blanking before re-use:</DT>
|
|
||||||
<DD>$<KBD> 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> 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> cdrskin -v dev=/dev/hdc speed=12 fs=8m \</KBD></DD>
|
|
||||||
<DD><KBD> -sao -eject padsize=300k my_image.iso</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Write compressed afio archive on-the-fly :</DT>
|
<DT>Write compressed afio archive on-the-fly :</DT>
|
||||||
<DD>$<KBD> find . | afio -oZ - | \</KBD></DD>
|
<DD>$ find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 driveropts=burnfree padsize=300k -tao -</DD>
|
||||||
<DD><KBD> cdrskin -v dev=0,1,0 fs=32m speed=8 \</KBD></DD>
|
<DT>Write audio tracks:</DT>
|
||||||
<DD><KBD> -tao padsize=300k -</KBD></DD>
|
<DD>$ cdrskin -v dev=ATA:1,0,0 speed=48 driveropts=burnfree -sao track1.wav track2.au -audio -swab track3.raw
|
||||||
|
<DD>
|
||||||
<DT>Write several sessions to the same CD or DVD-R[W]:</DT>
|
<BR>
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso</KBD>
|
<DT><A HREF="cdrskin_help">cdrskin -help</A></DT>
|
||||||
</DD>
|
<DD>reports the cdrecord compatible options</DD>
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso</KBD>
|
<DT><A HREF="cdrskin__help">cdrskin --help</A></DT>
|
||||||
</DD>
|
<DD>reports the non-cdrecord options</DD>
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 3.iso</KBD>
|
<DT><A HREF="http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html">man cdrecord</A></DT>
|
||||||
</DD>
|
<DD>documents the standard for which cdrskin is striving.
|
||||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -tao 4.iso</KBD></DD>
|
<B>Do not bother Joerg Schilling with any cdrskin problems.</B>
|
||||||
|
|
||||||
<DT>Get CD or DVD-R[W] multi-session info for option -C of program mkisofs:</DT>
|
|
||||||
<DD>$<KBD> c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)</KBD></DD>
|
|
||||||
<DD>$<KBD> mkisofs ... -C "$c_values" ...</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Write audio tracks to CD:</DT>
|
|
||||||
<DD>$<KBD> cdrskin -v dev=ATA:1,0,0 speed=48 -sao \</KBD></DD>
|
|
||||||
<DD><KBD> track1.wav track2.au -audio -swab track3.raw</KBD></DD>
|
|
||||||
|
|
||||||
<DT>Get overview of the cdrecord compatible options:</DT>
|
|
||||||
<DD>$<KBD> <A HREF="cdrskin_help">cdrskin -help</A></KBD></DD>
|
|
||||||
|
|
||||||
<DT>Get overview of the non-cdrecord options:</DT>
|
|
||||||
<DD>$<KBD> <A HREF="cdrskin__help">cdrskin --help</A></KBD></DD>
|
|
||||||
|
|
||||||
<DT>Read the detailed manual page:</DT>
|
|
||||||
<DD>$<KBD> <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>$<KBD>
|
|
||||||
<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
|
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
|
||||||
this "don't bother Joerg" demand.)
|
this "don't bother Joerg" demand.)
|
||||||
</DD>
|
</DD>
|
||||||
@ -190,9 +145,10 @@ rw-permissions and retry the bus scan as non-superuser.
|
|||||||
<P>
|
<P>
|
||||||
<DL>
|
<DL>
|
||||||
<DT>Download as source code (see README):</DT>
|
<DT>Download as source code (see README):</DT>
|
||||||
<DD><A HREF="cdrskin-0.3.2.pl00.tar.gz">cdrskin-0.3.2.pl00.tar.gz</A>
|
<DD><A HREF="cdrskin-0.2.6.pl02.tar.gz">cdrskin-0.2.6.pl02.tar.gz</A>
|
||||||
(570 KB).
|
(510 KB).
|
||||||
</DD>
|
</DD>
|
||||||
|
<DD>(Most recent patch: backported man page from cdrskin-0.2.7)</DD>
|
||||||
<DD>
|
<DD>
|
||||||
The "stable" cdrskin tarballs are source code identical with "stable"
|
The "stable" cdrskin tarballs are source code identical with "stable"
|
||||||
libburn releases or with "stabilized" libburn SVN snapshots. They get
|
libburn releases or with "stabilized" libburn SVN snapshots. They get
|
||||||
@ -201,14 +157,14 @@ cdrskin is part of libburn - full libburn is provided with cdrskin releases.
|
|||||||
</DD>
|
</DD>
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
|
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
|
||||||
<DD><A HREF="cdrskin_0.3.2.pl00-x86-suse9_0.tar.gz">
|
<DD><A HREF="cdrskin_0.2.6.pl01-x86-suse9_0.tar.gz">
|
||||||
cdrskin_0.3.2.pl00-x86-suse9_0.tar.gz</A>, (80 KB),
|
cdrskin_0.2.6.pl01-x86-suse9_0.tar.gz</A>, (60 KB),
|
||||||
<DL>
|
<DL>
|
||||||
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
|
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
|
||||||
Gentoo (2.6.15 x86_64 Athlon).</DD>
|
Gentoo (2.6.15 x86_64 Athlon).</DD>
|
||||||
</DL>
|
</DL>
|
||||||
<DD><A HREF="cdrskin_0.3.2.pl00-x86-suse9_0-static.tar.gz">
|
<DD><A HREF="cdrskin_0.2.6.pl01-x86-suse9_0-static.tar.gz">
|
||||||
cdrskin_0.3.2.pl00-x86-suse9_0-static.tar.gz</A>, (285 KB), -static compiled,
|
cdrskin_0.2.6.pl01-x86-suse9_0-static.tar.gz</A>, (260 KB), -static compiled,
|
||||||
<DL>
|
<DL>
|
||||||
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
|
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
|
||||||
</DL>
|
</DL>
|
||||||
@ -218,13 +174,10 @@ cdrskin_0.3.2.pl00-x86-suse9_0-static.tar.gz</A>, (285 KB), -static compiled,
|
|||||||
<DD><A HREF="README_cdrskin">README</A> a short introduction</DD>
|
<DD><A HREF="README_cdrskin">README</A> a short introduction</DD>
|
||||||
<DD><A HREF="cdrskin__help">cdrskin --help</A> non-cdrecord options</DD>
|
<DD><A HREF="cdrskin__help">cdrskin --help</A> non-cdrecord options</DD>
|
||||||
<DD><A HREF="cdrskin_help">cdrskin -help</A> cdrecord compatible options</DD>
|
<DD><A HREF="cdrskin_help">cdrskin -help</A> cdrecord compatible options</DD>
|
||||||
<DD><A HREF="man_1_cdrskin.html">man cdrskin</A> the manual page</DD>
|
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
</DL>
|
</DL>
|
||||||
<DL><DT>Contact:</DT>
|
<DL><DT>Contact:</DT>
|
||||||
<DD>Thomas Schmitt, <A HREF="mailto:scdbackup@gmx.net">scdbackup@gmx.net</A></DD>
|
<DD>Thomas Schmitt, <A HREF="mailto:scdbackup@gmx.net">scdbackup@gmx.net</A></DD>
|
||||||
<DD>libburn development mailing list,
|
|
||||||
<A HREF="mailto:libburn-hackers@pykix.org">libburn-hackers@pykix.org</A></DD>
|
|
||||||
</DL>
|
</DL>
|
||||||
<DL><DT>License:</DT>
|
<DL><DT>License:</DT>
|
||||||
<DD><A HREF="COPYING_cdrskin">GPL</A>, an <A HREF="http://www.opensource.org/">Open Source</A> approved license</DD>
|
<DD><A HREF="COPYING_cdrskin">GPL</A>, an <A HREF="http://www.opensource.org/">Open Source</A> approved license</DD>
|
||||||
@ -235,14 +188,23 @@ cdrskin_0.3.2.pl00-x86-suse9_0-static.tar.gz</A>, (285 KB), -static compiled,
|
|||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
Enhancements towards previous stable version cdrskin-0.3.0:
|
Enhancements towards previous stable version cdrskin-0.2.4:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>Burnfree enabled by default</LI>
|
<LI>Option <KBD><B>-tao</B></KBD> is fully enabled.<BR>
|
||||||
<LI>Multi-session burning to DVD-R
|
SAO is still the preferred default but TAO is default if a track of
|
||||||
and sequential (i.e. unformatted) DVD-RW</LI>
|
unpredicted size is present (stdin, named pipe, ...) or if a follow-up
|
||||||
<LI>Option -toc with sequential DVD-R[W]</LI>
|
session is written to an appendable CD.
|
||||||
<LI>Options -msinfo and msifile= with appendable DVD-R[W]</LI>
|
(This is an intentional deviation from cdrecord defaults which themselves
|
||||||
<LI>Single session DAO write mode with DVD-R[W]</LI>
|
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>
|
||||||
</UL>
|
</UL>
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
@ -250,21 +212,18 @@ and sequential (i.e. unformatted) DVD-RW</LI>
|
|||||||
|
|
||||||
<P>
|
<P>
|
||||||
<DL>
|
<DL>
|
||||||
<DT><H3>Development snapshot, version 0.3.3 :</H3></DT>
|
<DT><H3>Development snapshot, version 0.2.7 :</H3></DT>
|
||||||
<DD>Enhancements towards stable version 0.3.2:
|
<DD>Enhancements towards stable version 0.2.6:
|
||||||
<UL>
|
(none yet)
|
||||||
<LI>- none yet -</LI>
|
|
||||||
</UL>
|
|
||||||
</DD>
|
</DD>
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DD><A HREF="README_cdrskin_devel">README 0.3.3</A>
|
<DD><A HREF="README_cdrskin_devel">README 0.2.7</A>
|
||||||
<DD><A HREF="cdrskin__help_devel">cdrskin_0.3.3 --help</A></DD>
|
<DD><A HREF="cdrskin__help_devel">cdrskin_0.2.7 --help</A></DD>
|
||||||
<DD><A HREF="cdrskin_help_devel">cdrskin_0.3.3 -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.3.3)</A></DD>
|
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DT>Maintainers of cdrskin unstable packages please use SVN of
|
<DT>Maintainers of cdrskin unstable packages please use SVN of
|
||||||
<A HREF="http://libburnia.pykix.org"> libburnia.pykix.org</A></DT>
|
<A HREF="http://libburn.pykix.org"> libburn.pykix.org</A></DT>
|
||||||
<DD>Download: <KBD><B>svn co http://libburnia-svn.pykix.org/libburn/trunk libburn_pykix</B>
|
<DD>Download: <KBD><B>svn co http://libburn-svn.pykix.org/libburn/trunk libburn_pykix</B>
|
||||||
</KBD></DD>
|
</KBD></DD>
|
||||||
<DD>Build: <KBD><B>cd libburn_pykix ; ./bootstrap ; ./configure ; make</B>
|
<DD>Build: <KBD><B>cd libburn_pykix ; ./bootstrap ; ./configure ; make</B>
|
||||||
</KBD></DD>
|
</KBD></DD>
|
||||||
@ -276,19 +235,19 @@ vanilla tools like make and gcc are needed.</DD>
|
|||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DT>The following downloads are intended for adventurous end users or
|
<DT>The following downloads are intended for adventurous end users or
|
||||||
admins with full system souvereignty.</DT>
|
admins with full system souvereignty.</DT>
|
||||||
<DD>Source (./bootstrap is already applied, build tested, for more see
|
<DD>Source (./bootstrap is already applied, build tested, for more see above
|
||||||
<A HREF="README_cdrskin_devel">upcoming README</A> ):
|
<A HREF="README_cdrskin_devel">upcoming README</A> ):
|
||||||
</DD>
|
</DD>
|
||||||
<DD>
|
<DD>
|
||||||
<A HREF="cdrskin-0.3.3.tar.gz">cdrskin-0.3.3.tar.gz</A>
|
<A HREF="cdrskin-0.2.7.tar.gz">cdrskin-0.2.7.tar.gz</A>
|
||||||
(570 KB).
|
(500 KB).
|
||||||
</DD>
|
</DD>
|
||||||
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
|
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
|
||||||
<DD><A HREF="cdrskin_0.3.3-x86-suse9_0.tar.gz">
|
<DD><A HREF="cdrskin_0.2.7-x86-suse9_0.tar.gz">
|
||||||
cdrskin_0.3.3-x86-suse9_0.tar.gz</A>, (80 KB).
|
cdrskin_0.2.7-x86-suse9_0.tar.gz</A>, (60 KB).
|
||||||
</DD>
|
</DD>
|
||||||
<DD><A HREF="cdrskin_0.3.3-x86-suse9_0-static.tar.gz">
|
<DD><A HREF="cdrskin_0.2.7-x86-suse9_0-static.tar.gz">
|
||||||
cdrskin_0.3.3-x86-suse9_0-static.tar.gz</A>, (280 KB)
|
cdrskin_0.2.7-x86-suse9_0-static.tar.gz</A>, (260 KB)
|
||||||
</DD>
|
</DD>
|
||||||
</DL>
|
</DL>
|
||||||
</P>
|
</P>
|
||||||
@ -304,10 +263,6 @@ Historic versions based on Derek's and Ben's
|
|||||||
<A HREF="http://icculus.org/burn">icculus.org/burn</A> :<BR>
|
<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.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>
|
<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>
|
</P>
|
||||||
|
|
||||||
<HR>
|
<HR>
|
||||||
@ -350,7 +305,7 @@ is a GUI frontend which uses cdrecord for CD burning.)
|
|||||||
<DD><KBD>...</KBD></DD>
|
<DD><KBD>...</KBD></DD>
|
||||||
<DD><KBD> 1,0,0 1) 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
|
<DD><KBD> 1,0,0 1) '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_SCSI_ADR="ATA:1,0,0"</B></KBD></DD>
|
||||||
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v"</B></KBD></DD>
|
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v tao_to_sao_tsize=650m"</B></KBD></DD>
|
||||||
<DD>$ <KBD><B>scdbackup_home</B></KBD></DD>
|
<DD>$ <KBD><B>scdbackup_home</B></KBD></DD>
|
||||||
</DL>
|
</DL>
|
||||||
<DL>
|
<DL>
|
||||||
@ -359,7 +314,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>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
|
||||||
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
|
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
|
||||||
<DD><KBD>...</KBD></DD>
|
<DD><KBD>...</KBD></DD>
|
||||||
<DD><KBD>cdrskin 0.3.2 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
|
<DD><KBD>cdrskin 0.2.6 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
|
||||||
</DL>
|
</DL>
|
||||||
If your system is stricken with some ill CD device then this can stall
|
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.
|
and you will have to press <KBD>Ctrl+C</KBD> to abort.
|
||||||
@ -417,11 +372,10 @@ the gestures necessary for their cdrecord applications.
|
|||||||
Contact me. Let's see what we can achieve.
|
Contact me. Let's see what we can achieve.
|
||||||
<BR>
|
<BR>
|
||||||
<BR>
|
<BR>
|
||||||
libburn and cdrskin are now mature enough to substitute cdrecord in its
|
I am aware that libburn and cdrskin still have way to go until you can simply
|
||||||
major use cases of CD burning. It is possible to foist cdrskin on various
|
install cdrskin as cdrecord and may expect any application to run with it.
|
||||||
software packages if it gets falsely named "cdrecord".
|
Currently i do not encourage this approach, but of course such a replacement
|
||||||
I do not encourage this approach, but of course such a replacement
|
opportunity is the long term goal of a cdrecord compatibility wrapper.
|
||||||
opportunity is the goal of a cdrecord compatibility wrapper.
|
|
||||||
<BR>
|
<BR>
|
||||||
<BR>
|
<BR>
|
||||||
It is very important to me that this project is not perceived as hostile
|
It is very important to me that this project is not perceived as hostile
|
||||||
@ -435,10 +389,6 @@ I owe him much. For cdrecord, for mkisofs, for star. Chapeau.
|
|||||||
<!-- <A NAME="bottom" HREF="main_ger.html#bottom">deutsch (german)</A>
|
<!-- <A NAME="bottom" HREF="main_ger.html#bottom">deutsch (german)</A>
|
||||||
<BR><BR>
|
<BR><BR>
|
||||||
-->
|
-->
|
||||||
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
|
||||||
<IMG SRC="doener_150x200_tr.gif" BORDER=0
|
|
||||||
ALT="cdrskin logo: Doener mit Scharf"></A>
|
|
||||||
<BR><BR>
|
|
||||||
<FONT SIZE=+0>Enjoying free Open Source hosting by <A HREF="http://www.webframe.org">www.webframe.org</A><BR>
|
<FONT SIZE=+0>Enjoying free Open Source hosting by <A HREF="http://www.webframe.org">www.webframe.org</A><BR>
|
||||||
<A HREF="http://www.webframe.org">
|
<A HREF="http://www.webframe.org">
|
||||||
<IMG SRC="msfree.gif" ALT="100 % Microsoft free" BORDER=0></A><BR>
|
<IMG SRC="msfree.gif" ALT="100 % Microsoft free" BORDER=0></A><BR>
|
||||||
|
@ -1 +1 @@
|
|||||||
#define Cdrskin_timestamP "2007.02.10.120001"
|
#define Cdrskin_timestamP "2006.12.16.090001"
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -63,9 +63,9 @@ static int signal_list_count= 24;
|
|||||||
|
|
||||||
/* Signals not to be caught */
|
/* Signals not to be caught */
|
||||||
static int non_signal_list[]= {
|
static int non_signal_list[]= {
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1
|
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, -1
|
||||||
};
|
};
|
||||||
static int non_signal_list_count= 5;
|
static int non_signal_list_count= 4;
|
||||||
|
|
||||||
|
|
||||||
#endif /* Cleanup_has_no_libburn_os_H */
|
#endif /* Cleanup_has_no_libburn_os_H */
|
||||||
@ -75,7 +75,6 @@ static int non_signal_list_count= 5;
|
|||||||
/* run time dynamic part */
|
/* run time dynamic part */
|
||||||
static char cleanup_msg[4096]= {""};
|
static char cleanup_msg[4096]= {""};
|
||||||
static int cleanup_exiting= 0;
|
static int cleanup_exiting= 0;
|
||||||
static int cleanup_has_reported= -1234567890;
|
|
||||||
|
|
||||||
static void *cleanup_app_handle= NULL;
|
static void *cleanup_app_handle= NULL;
|
||||||
static Cleanup_app_handler_T cleanup_app_handler= NULL;
|
static Cleanup_app_handler_T cleanup_app_handler= NULL;
|
||||||
@ -86,10 +85,8 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) {
|
if(cleanup_msg[0]!=0)
|
||||||
fprintf(stderr,"\n%s\n",cleanup_msg);
|
fprintf(stderr,"\n%s\n",cleanup_msg);
|
||||||
cleanup_has_reported= signum;
|
|
||||||
}
|
|
||||||
if(cleanup_perform_app_handler_first)
|
if(cleanup_perform_app_handler_first)
|
||||||
if(cleanup_app_handler!=NULL) {
|
if(cleanup_app_handler!=NULL) {
|
||||||
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
|
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
debug_opts=
|
debug_opts=
|
||||||
def_opts=
|
def_opts=
|
||||||
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
|
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
|
||||||
libvers="-DCdrskin_libburn_0_3_2"
|
libvers="-DCdrskin_libburn_0_2_6"
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
cleanup_src_or_obj="libburn/cleanup.o"
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
libdax_msgs_o="libburn/libdax_msgs.o"
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
||||||
@ -33,15 +33,15 @@ do
|
|||||||
libdax_audioxtr_o=
|
libdax_audioxtr_o=
|
||||||
libdax_msgs_o="libburn/message.o"
|
libdax_msgs_o="libburn/message.o"
|
||||||
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
|
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
|
||||||
elif test "$i" = "-libburn_0_3_2"
|
elif test "$i" = "-libburn_0_2_6"
|
||||||
then
|
then
|
||||||
libvers="-DCdrskin_libburn_0_3_2"
|
libvers="-DCdrskin_libburn_0_2_6"
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
libdax_msgs_o="libburn/libdax_msgs.o"
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
cleanup_src_or_obj="libburn/cleanup.o"
|
||||||
elif test "$i" = "-libburn_svn"
|
elif test "$i" = "-libburn_svn"
|
||||||
then
|
then
|
||||||
libvers="-DCdrskin_libburn_0_3_3"
|
libvers="-DCdrskin_libburn_0_2_6"
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
libdax_msgs_o="libburn/libdax_msgs.o"
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
cleanup_src_or_obj="libburn/cleanup.o"
|
||||||
@ -79,7 +79,7 @@ do
|
|||||||
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
|
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
|
||||||
echo " -compile_dewav compile program test/dewav without libburn."
|
echo " -compile_dewav compile program test/dewav without libburn."
|
||||||
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
|
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
|
||||||
echo " -libburn_0_3_2 set macro to match libburn-0.3.2."
|
echo " -libburn_0_2_6 set macro to match libburn-0.2.6."
|
||||||
echo " -libburn_svn set macro to match current libburn-SVN."
|
echo " -libburn_svn set macro to match current libburn-SVN."
|
||||||
echo " -no_largefile do not use 64 bit off_t (must match libburn)."
|
echo " -no_largefile do not use 64 bit off_t (must match libburn)."
|
||||||
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
|
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#
|
|
||||||
# convert_man_to_html.sh - ts A61214
|
|
||||||
#
|
|
||||||
# Generates a HTML version of man page cdrskin.1
|
|
||||||
#
|
|
||||||
# To be executed within the libburn toplevel directory (like ./libburn-0.2.7)
|
|
||||||
#
|
|
||||||
|
|
||||||
# set -x
|
|
||||||
|
|
||||||
man_dir=$(pwd)"/cdrskin"
|
|
||||||
export MANPATH="$man_dir"
|
|
||||||
manpage="cdrskin"
|
|
||||||
raw_html=$(pwd)/"cdrskin/raw_man_1_cdrskin.html"
|
|
||||||
htmlpage=$(pwd)/"cdrskin/man_1_cdrskin.html"
|
|
||||||
|
|
||||||
if test -r "$manpage"
|
|
||||||
then
|
|
||||||
dummy=dummy
|
|
||||||
else
|
|
||||||
echo "Cannot find readable man page source $1" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test -e "$man_dir"/man1
|
|
||||||
then
|
|
||||||
dummy=dummy
|
|
||||||
else
|
|
||||||
ln -s . "$man_dir"/man1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$1" = "-work_as_filter"
|
|
||||||
then
|
|
||||||
|
|
||||||
# set -x
|
|
||||||
|
|
||||||
sed \
|
|
||||||
-e 's/<meta name="generator" content="groff -Thtml, see www.gnu.org">/<meta name="generator" content="groff -Thtml, via man -H, via cdrskin\/convert_man_to_html.sh">/' \
|
|
||||||
-e 's/<meta name="Content-Style" content="text\/css">/<meta name="Content-Style" content="text\/css"><META NAME="description" CONTENT="man page of cdrskin"><META NAME="keywords" CONTENT="man cdrskin, manual, cdrskin, CD, CD-RW, CD-R, burning, cdrecord, compatible"><META NAME="robots" CONTENT="follow">/' \
|
|
||||||
-e 's/<title>CDRSKIN<\/title>/<title>man 1 cdrskin<\/title>/' \
|
|
||||||
-e 's/<h1 align=center>CDRSKIN<\/h1>/<h1 align=center>man 1 cdrskin<\/h1>/' \
|
|
||||||
-e 's/<body>/<body BGCOLOR="#F5DEB3" TEXT=#000000 LINK=#0000A0 VLINK=#800000>/' \
|
|
||||||
-e 's/<b>Overview of features:<\/b>/\ <BR><b>Overview of features:<\/b>/' \
|
|
||||||
-e 's/<b>Track recording model:<\/b>/\ <BR><b>Track recording model:<\/b>/' \
|
|
||||||
-e 's/In general there are two types of tracks: data and audio./\ <BR>In general there are two types of tracks: data and audio./' \
|
|
||||||
-e 's/While audio tracks just contain a given/\ <BR>While audio tracks just contain a given/' \
|
|
||||||
-e 's/<b>Recordable CD Media:<\/b>/\ <BR><b>Recordable CD Media:<\/b>/' \
|
|
||||||
-e 's/<b>Overwriteable DVD Media:<\/b>/\ <BR><b>Overwriteable DVD Media:<\/b>/' \
|
|
||||||
-e 's/<b>Sequentially Recordable DVD Media:<\/b>/\ <BR><b>Sequentially Recordable DVD Media:<\/b>/' \
|
|
||||||
-e 's/<b>Drive preparation and addressing:<\/b>/\ <BR><b>Drive preparation and addressing:<\/b>/' \
|
|
||||||
-e 's/If you only got one CD capable drive/\ <BR>If you only got one CD capable drive/' \
|
|
||||||
-e 's/^Alphabetical list of options/\ <BR>Alphabetical list of options/' \
|
|
||||||
-e 's/and for all others\.<\/td><\/table>/and for all others.<\/td><\/table> <BR><HR><FONT SIZE=-1><CENTER>(HTML generated from '"$manpage"'.1 on '"$(date)"' by '$(basename "$0")' )<\/CENTER><\/FONT>/' \
|
|
||||||
-e 's/See section EXAMPLES/See section <A HREF="#EXAMPLES">EXAMPLES<\/A>/' \
|
|
||||||
<"$2" >"$htmlpage"
|
|
||||||
|
|
||||||
set +x
|
|
||||||
|
|
||||||
chmod u+rw,go+r,go-w "$htmlpage"
|
|
||||||
echo "Emerged file:"
|
|
||||||
ls -l "$htmlpage"
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
export BROWSER='cp "%s" '"$raw_html"
|
|
||||||
man -H "$manpage"
|
|
||||||
"$0" -work_as_filter "$raw_html"
|
|
||||||
rm "$raw_html"
|
|
||||||
rm "$man_dir"/man1
|
|
||||||
|
|
||||||
fi
|
|
Binary file not shown.
Before Width: | Height: | Size: 34 KiB |
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
@ -1,42 +1,35 @@
|
|||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
cdrskin Wiki - plain text copy
|
cdrskin Wiki - plain text copy
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
[[Image(source:/libburn/trunk/cdrskin/doener_150x200_tr.gif)]] [http://en.wikipedia.org/wiki/D%C3%B6ner_kebab Doener]
|
|
||||||
|
|
||||||
'''cdrskin is the cdrecord compatibility middleware of libburn.'''
|
cdrskin is the cdrecord compatibility middleware of libburn.
|
||||||
|
|
||||||
Its paragon, cdrecord, is a powerful GPL'ed burn program included in Joerg
|
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
|
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 this way.
|
traditionally provided by cdrecord. Currently it does CD-R and CD-RW.
|
||||||
Overwriteable media DVD-RAM, DVD+RW and DVD-RW are handled differently than
|
Its future ability to burn DVD media depends on the development of libburn.
|
||||||
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.
|
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||||
Many bytes have been copied from the message output of cdrecord
|
Many bytes have been copied from the message output of cdrecord
|
||||||
runs, though. The most comprehensive technical overview of cdrskin
|
runs, though. The most comprehensive technical overview of cdrskin
|
||||||
can be found in [http://libburnia.pykix.org/browser/libburn/trunk/cdrskin/README?format=txt cdrskin/README].
|
can be found in cdrskin/README . Online available as :
|
||||||
|
http://libburn.pykix.org/browser/trunk/cdrskin/README?format=raw
|
||||||
|
|
||||||
About libburn API for burning CD: http://libburnia-api.pykix.org
|
About libburn API for burning CD: http://libburn-api.pykix.org
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
Appending sessions to an unclosed CD or DVD-R[W] is restricted to write mode
|
Appending sessions to an unclosed CD is restricted to write mode TAO.
|
||||||
TAO. (Users who have a burner which succeeds with a follow-up session on CD via
|
(Users who have a burner which succeeds with a follow-up session via
|
||||||
cdrecord -sao : please contact us.)
|
cdrecord -sao : please contact us.)
|
||||||
|
|
||||||
For DVD types other than DVD-RAM, DVD+RW, DVD-RW, DVD-R and for appending
|
cdrskin does not provide DVD burning yet. See advise to use dvd+rw-tools
|
||||||
sessions to ISO filesystems on DVD other than DVD-RW, DVD-R see the advise
|
at the end of this text.
|
||||||
to use dvd+rw-tools at the end of this text.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
About the command line options of cdrskin:
|
About the command line options of cdrskin:
|
||||||
|
|
||||||
They are described in detail in [http://scdbackup.sourceforge.net/man_1_cdrskin_devel.html#OPTIONS section OPTIONS] of
|
|
||||||
[http://scdbackup.sourceforge.net/man_1_cdrskin_devel.html man cdrskin]
|
|
||||||
|
|
||||||
There are two families of options: cdrecord-compatible ones and options
|
There are two families of options: cdrecord-compatible ones and options
|
||||||
which are specific to cdrskin. The latter are mostly used to configure
|
which are specific to cdrskin. The latter are mostly used to configure
|
||||||
cdrskin for its task to emulate cdrecord. There are some, nevertheless,
|
cdrskin for its task to emulate cdrecord. There are some, nevertheless,
|
||||||
@ -46,10 +39,9 @@ The cdrecord-compatible options are listed in the output of
|
|||||||
{{{
|
{{{
|
||||||
cdrskin -help
|
cdrskin -help
|
||||||
}}}
|
}}}
|
||||||
where the option "help" has *one* dash. Online: [http://scdbackup.sourceforge.net/cdrskin_help_devel cdrskin -help]
|
where the option "help" has *one* dash.
|
||||||
|
|
||||||
For these options you may expect program behavior that is roughly the
|
For these options you may expect program behavior that is roughly the
|
||||||
same as described in original man cdrecord .
|
same as described in original man 1 cdrecord .
|
||||||
|
|
||||||
Online: http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html
|
Online: http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html
|
||||||
|
|
||||||
@ -57,10 +49,10 @@ The cdrskin-specific options are listed by
|
|||||||
{{{
|
{{{
|
||||||
cdrskin --help
|
cdrskin --help
|
||||||
}}}
|
}}}
|
||||||
where the option "help" has *two* dashes. Online: [http://scdbackup.sourceforge.net/cdrskin__help_devel cdrskin --help]
|
where the option "help" has *two* dashes.
|
||||||
|
|
||||||
Some are very experimental and should only be
|
Those have no man page yet. Some are very experimental and should only be
|
||||||
used in coordination with the libburnia developer team.
|
used in coordination with the libburn developer team.
|
||||||
Some are of general user interest, though:
|
Some are of general user interest, though:
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
@ -85,44 +77,6 @@ has to offer both, r- and w-permission.
|
|||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
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".
|
|
||||||
{{{
|
|
||||||
cdrskin dev=/dev/sr0 -v blank=format_overwrite
|
|
||||||
}}}
|
|
||||||
|
|
||||||
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
|
fifo_start_at=<num> is a throughput enhancer for unsteady data streams
|
||||||
like they are produced by a compressing archiver program when piping to
|
like they are produced by a compressing archiver program when piping to
|
||||||
CD on-the-fly. It makes better use of the general property of a FIFO
|
CD on-the-fly. It makes better use of the general property of a FIFO
|
||||||
@ -172,12 +126,25 @@ default settings of cdrskin. Possible locations for such settings:
|
|||||||
|
|
||||||
/etc/opt/cdrskin/rc
|
/etc/opt/cdrskin/rc
|
||||||
|
|
||||||
/etc/cdrskin/cdrskin.conf
|
|
||||||
|
|
||||||
$HOME/.cdrskinrc
|
$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
|
dev_translation=<sep><from><sep><to> may be needed to foist cdrskin to
|
||||||
frontend programs of cdrecord which do *not* ask cdrecord -scanbus but
|
frontend programs of cdrecord which do *not* ask cdrecord -scanbus but
|
||||||
which make own assumptions and guesses about cdrecord's device addresses.
|
which make own assumptions and guesses about cdrecord's device addresses.
|
||||||
@ -209,10 +176,9 @@ for an illustrated example with K3b 0.10 .
|
|||||||
|
|
||||||
DVD advise:
|
DVD advise:
|
||||||
|
|
||||||
For burning of DVD media other than DVD-RAM, DVD+RW, DVD-RW, DVD-R, the cdrskin
|
For burning of DVD media the cdrskin project currently advises to use
|
||||||
project currently advises to use Andy Polyakov's dvd+rw-tools which despite
|
Andy Polyakov's dvd+rw-tools which despite their historic name burn
|
||||||
their historic name burn for me on above burner: DVD-RAM, DVD+RW, DVD+R,
|
for me on above burner: DVD+RW, DVD+R, 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
|
http://fy.chalmers.se/~appro/linux/DVD+RW/tools
|
||||||
|
|
||||||
@ -220,18 +186,24 @@ They are not compatible or related to cdrecord resp. cdrecord-ProDVD
|
|||||||
(now obsoleted by original source cdrtools cdrecord with identical
|
(now obsoleted by original source cdrtools cdrecord with identical
|
||||||
capabilities besides the license key).
|
capabilities besides the license key).
|
||||||
|
|
||||||
A special feature of dvd+rw-tools is growing of ISO-9660 filesystems on
|
If there is sincere and well motivated interest, the cdrskin project could try
|
||||||
overwriteable media. This is not the same as multi-session writing of cdrskin
|
to employ growisofs as DVD burning engine. The cdrskin project would prefer to
|
||||||
with CD media, but retrieves additional information from the existing ISO
|
wait for DVD support being included in libburn, though.
|
||||||
image and finally manipulates the start sectors of this existing image.
|
A very limited and specialized cdrecord-compatibility wrapper for growisofs
|
||||||
So for growable ISO filesystems on DVD-RAM or DVD+RW growisofs is the only
|
serves in my project scdbackup. It is not overly hard to make one that serves
|
||||||
choice, currently.
|
some very few fixed use cases.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
cdrskin can offer DVD multi-session only with sequential DVD-R[W]. Associated
|
Beware of the impact of a slow block device on overall system i/o buffering.
|
||||||
options blank=, -multi, -msinfo and -toc are available in this case. Thus
|
It is wise to curb its input to a speed which it is able to deliver to media.
|
||||||
sequential DVD-RW behave much like large CD-RW with possibly more than 99
|
Else your i/o dedicated RAM might buffer a big amount of stream data.
|
||||||
tracks.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
19
configure.ac
19
configure.ac
@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libburn], [0.3.2], [http://libburnia.pykix.org])
|
AC_INIT([libburn], [0.2.6.2], [http://libburn.pykix.org])
|
||||||
AC_PREREQ([2.50])
|
AC_PREREQ([2.50])
|
||||||
dnl AC_CONFIG_HEADER([config.h])
|
dnl AC_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
@ -7,6 +7,12 @@ AC_CANONICAL_TARGET
|
|||||||
|
|
||||||
AM_INIT_AUTOMAKE([subdir-objects])
|
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 Making releases:
|
||||||
dnl BURN_MICRO_VERSION += 1;
|
dnl BURN_MICRO_VERSION += 1;
|
||||||
dnl BURN_INTERFACE_AGE += 1;
|
dnl BURN_INTERFACE_AGE += 1;
|
||||||
@ -18,8 +24,8 @@ dnl
|
|||||||
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
|
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
|
||||||
dnl
|
dnl
|
||||||
BURN_MAJOR_VERSION=0
|
BURN_MAJOR_VERSION=0
|
||||||
BURN_MINOR_VERSION=3
|
BURN_MINOR_VERSION=2
|
||||||
BURN_MICRO_VERSION=2
|
BURN_MICRO_VERSION=6.2
|
||||||
BURN_INTERFACE_AGE=0
|
BURN_INTERFACE_AGE=0
|
||||||
BURN_BINARY_AGE=0
|
BURN_BINARY_AGE=0
|
||||||
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
||||||
@ -57,7 +63,6 @@ AC_C_BIGENDIAN
|
|||||||
dnl Large file support
|
dnl Large file support
|
||||||
AC_SYS_LARGEFILE
|
AC_SYS_LARGEFILE
|
||||||
AC_FUNC_FSEEKO
|
AC_FUNC_FSEEKO
|
||||||
AC_CHECK_FUNC([fseeko])
|
|
||||||
if test ! $ac_cv_func_fseeko; then
|
if test ! $ac_cv_func_fseeko; then
|
||||||
AC_ERROR([Libburn requires largefile support.])
|
AC_ERROR([Libburn requires largefile support.])
|
||||||
fi
|
fi
|
||||||
@ -70,6 +75,12 @@ AC_PROG_INSTALL
|
|||||||
|
|
||||||
AC_CHECK_HEADERS()
|
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
|
THREAD_LIBS=-lpthread
|
||||||
AC_SUBST(THREAD_LIBS)
|
AC_SUBST(THREAD_LIBS)
|
||||||
|
|
||||||
|
74
doc/comments
74
doc/comments
@ -1,14 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
@author Mario Danic, Thomas Schmitt
|
@author Mario Danic, Thomas Schmitt
|
||||||
|
|
||||||
@mainpage Libburnia Documentation Index
|
@mainpage Libburn Documentation Index
|
||||||
|
|
||||||
@section intro Introduction
|
@section intro Introduction
|
||||||
|
|
||||||
Libburnia is an open-source project for reading, mastering and writing
|
Libburn is an open-source library for reading, mastering and writing
|
||||||
optical discs. For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD-RW, DVD-R.
|
optical discs. For now this means only CD-R and CD-RW.
|
||||||
|
|
||||||
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
|
The project comprises of several more or less interdependent parts which
|
||||||
together strive to be a usable foundation for application development.
|
together strive to be a usable foundation for application development.
|
||||||
@ -20,22 +18,19 @@ 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,
|
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
|
||||||
volunteers for testing of realistic use cases.
|
volunteers for testing of realistic use cases.
|
||||||
|
|
||||||
We have a workable code base for burning data and audio CDs and many DVD types.
|
We do have a workable code base for burning data CDs, though. The burn API is
|
||||||
The burn API is quite comprehensively documented and can be used to build a
|
quite comprehensively documented and can be used to build a presentable
|
||||||
presentable application.
|
application.
|
||||||
We have a functional binary which emulates the core use cases of cdrecord in
|
We do have a functional binary which emulates parts of cdrecord in order to
|
||||||
order to prove that usability, and in order to allow you to explore libburn's
|
prove that usability, and in order to allow you to explore libburn's scope
|
||||||
scope by help of existing cdrecord frontends.
|
by help of existing cdrecord frontends.
|
||||||
|
|
||||||
@subsection components The project components (list subject to growth, hopefully):
|
@subsection components The project components (list subject to growth, hopefully):
|
||||||
|
|
||||||
- libburn is the library by which preformatted data get onto optical media.
|
- 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
|
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
|
||||||
/dev/hdX (e.g. on kernel 2.6).
|
/dev/hdX (e.g. on kernel 2.6).
|
||||||
libburn is the foundation of our cdrecord emulation. Its code is
|
libburn is the foundation of our cdrecord emulation.
|
||||||
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
|
- 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 CD via libburn.
|
||||||
@ -44,18 +39,15 @@ scope by help of existing cdrecord frontends.
|
|||||||
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
||||||
cdrecord is a powerful GPL'ed burn program included in Joerg
|
cdrecord is a powerful GPL'ed burn program included in Joerg
|
||||||
Schilling's cdrtools. cdrskin strives to be a second source for
|
Schilling's cdrtools. cdrskin strives to be a second source for
|
||||||
the services traditionally provided by cdrecord. Additionally it
|
the services traditionally provided by cdrecord.
|
||||||
provides libburn's DVD capabilities, where only -sao is compatible
|
|
||||||
with cdrecord.
|
|
||||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||||
Many bytes have been copied from the message output of cdrecord
|
Many bytes have been copied from the message output of cdrecord
|
||||||
runs, though.
|
runs, though.
|
||||||
See cdrskin/README for more.
|
See cdrskin/README for more.
|
||||||
|
|
||||||
- "test" is a collection of application gestures and examples given by the
|
- "test" is a collection of application gestures and examples given by the
|
||||||
authors of the library features. The burn API example of libburn
|
authors of the library features. The main API example of libburn
|
||||||
is named test/libburner.c . The API for media information inquiry is
|
is named test/libburner.c .
|
||||||
demonstrated in test/telltoc.c .
|
|
||||||
Explore these examples if you look for inspiration.
|
Explore these examples if you look for inspiration.
|
||||||
|
|
||||||
We plan to be a responsive upstream. Bear with us.
|
We plan to be a responsive upstream. Bear with us.
|
||||||
@ -88,11 +80,11 @@ languages and development tools.
|
|||||||
|
|
||||||
libburner is a minimal demo application for the library libburn
|
libburner is a minimal demo application for the library libburn
|
||||||
(see: libburn/libburn.h) as provided on http://libburn.pykix.org .
|
(see: libburn/libburn.h) as provided on http://libburn.pykix.org .
|
||||||
It can list the available devices, can blank a CD-RW or DVD-RW and
|
It can list the available devices, can blank a CD-RW and
|
||||||
can burn to CD-R, CD-RW, DVD-RAM, DVD+RW, DVD-RW, DVD-R.
|
can burn to CD-R or CD-RW.
|
||||||
|
|
||||||
It's main purpose, nevertheless, is to show you how to use libburn and also
|
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
|
to serve the libburn team as reference application. libburner does indeed
|
||||||
define the standard way how above three gestures can be implemented and
|
define the standard way how above three gestures can be implemented and
|
||||||
stay upward compatible for a good while.
|
stay upward compatible for a good while.
|
||||||
|
|
||||||
@ -100,43 +92,27 @@ stay upward compatible for a good while.
|
|||||||
<pre>
|
<pre>
|
||||||
Usage: test/libburner
|
Usage: test/libburner
|
||||||
[--drive <address>|<driveno>|"-"] [--audio]
|
[--drive <address>|<driveno>|"-"] [--audio]
|
||||||
[--blank_fast|--blank_full|--format_overwrite]
|
[--blank_fast|--blank_full] [--try_to_simulate]
|
||||||
[--try_to_simulate]
|
[<one or more imagefiles>|"-"]
|
||||||
[--multi] [<one or more imagefiles>|"-"]
|
|
||||||
Examples
|
Examples
|
||||||
A bus scan (needs rw-permissions to see a drive):
|
A bus scan (needs rw-permissions to see a drive):
|
||||||
test/libburner --drive -
|
test/libburner --drive -
|
||||||
Burn a file to drive chosen by number, leave appendable:
|
Burn a file to drive chosen by number:
|
||||||
test/libburner --drive 0 --multi my_image_file
|
test/libburner --drive 0 my_image_file
|
||||||
Burn a file to drive chosen by persistent address, close:
|
Burn a file to drive chosen by persistent address:
|
||||||
test/libburner --drive /dev/hdc my_image_file
|
test/libburner --drive /dev/hdc my_image_file
|
||||||
Blank a used CD-RW (is combinable with burning in one run):
|
Blank a used CD-RW (is combinable with burning in one run):
|
||||||
test/libburner --drive /dev/hdc --blank_fast
|
test/libburner --drive /dev/hdc --blank_fast
|
||||||
Blank a used DVD-RW (is combinable with burning in one run):
|
Burn two audio tracks
|
||||||
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
|
lame --decode -t /path/to/track1.mp3 track1.cd
|
||||||
test/dewav /path/to/track2.wav -o track2.cd
|
test/dewav /path/to/track2.wav -o track2.cd
|
||||||
test/libburner --drive /dev/hdc --audio track1.cd track2.cd
|
test/libburner --drive /dev/hdc --audio track1.cd track2.cd
|
||||||
Burn a compressed afio archive on-the-fly:
|
Burn a compressed afio archive on-the-fly, pad up to 700 MB:
|
||||||
( cd my_directory ; find . -print | afio -oZ - ) | \
|
( cd my_directory ; find . -print | afio -oZ - ) | \
|
||||||
test/libburner --drive /dev/hdc -
|
test/libburner --drive /dev/hdc -
|
||||||
To be read from *not mounted* media via: afio -tvZ /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.
|
||||||
</pre>
|
</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 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)
|
|
||||||
or .au (SUN Audio). See example in libburner --help.
|
|
||||||
|
|
||||||
@subsection libburner-source Sourceode of libburner
|
@subsection libburner-source Sourceode of libburner
|
||||||
|
|
||||||
|
121
doc/comments_test_ts
Normal file
121
doc/comments_test_ts
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
@author Mario Danic, Thomas Schmitt
|
||||||
|
|
||||||
|
@mainpage Libburn Documentation Index
|
||||||
|
|
||||||
|
@section intro Introduction
|
||||||
|
|
||||||
|
Libburn is an open-source library for reading, mastering and writing
|
||||||
|
optical discs. For now this means only CD-R and CD-RW.
|
||||||
|
|
||||||
|
The project comprises of several more or less interdependent parts which
|
||||||
|
together strive to be a usable foundation for application development.
|
||||||
|
These are libraries, language bindings, and middleware binaries which emulate
|
||||||
|
classical (and valuable) Linux tools.
|
||||||
|
|
||||||
|
Our scope is currently Linux 2.4 and 2.6 and we will have a hard time to widen
|
||||||
|
this for now, because of our history. The project could need advise from or
|
||||||
|
membership of skilled kernel people and people who know how to talk CD/DVD
|
||||||
|
drives into doing things.
|
||||||
|
|
||||||
|
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
|
||||||
|
prove that usability, and in order to allow you to explore libburn's scope
|
||||||
|
by help of existing cdrecord frontends.
|
||||||
|
|
||||||
|
@subsection components 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.
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
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.
|
||||||
|
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 .
|
||||||
|
Explore these examples if you look for inspiration.
|
||||||
|
|
||||||
|
We plan to be a responsive upstream. Bear with us.
|
||||||
|
|
||||||
|
|
||||||
|
@section using Using the libraries
|
||||||
|
|
||||||
|
Our build system is based on autotools.
|
||||||
|
User experience tells us that you will need at least autotools version 1.7.
|
||||||
|
|
||||||
|
To build libburn and its subprojects it should be sufficient to go into
|
||||||
|
its toplevel directory and execute
|
||||||
|
|
||||||
|
- ./bootstrap (needed if you downloaded from SVN)
|
||||||
|
|
||||||
|
- ./configure
|
||||||
|
|
||||||
|
- make
|
||||||
|
|
||||||
|
To make the libraries accessible for running resp. developing applications
|
||||||
|
|
||||||
|
- make install
|
||||||
|
|
||||||
|
Both libraries are written in C language and get built by autotools.
|
||||||
|
Thus we expect them to be useable by a wide range of Linux-implemented
|
||||||
|
languages and development tools.
|
||||||
|
|
||||||
|
|
||||||
|
@section libburner Libburner
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
It's main purpose, nevertheless, is to show you how to use libburn and also
|
||||||
|
to serve the libburn team as reference application. libburner does indeed
|
||||||
|
define the standard way how above three gestures can be implemented and
|
||||||
|
stay upward compatible for a good while.
|
||||||
|
|
||||||
|
@subsection libburner-help Libburner --help
|
||||||
|
<pre>
|
||||||
|
Usage: test/libburner
|
||||||
|
[--drive <address>|<driveno>|"-"]
|
||||||
|
[--verbose <level>] [--blank_fast|--blank_full]
|
||||||
|
[--burn_for_real|--try_to_simulate] [--stdin_size <bytes>]
|
||||||
|
[<imagefile>|"-"]
|
||||||
|
Examples
|
||||||
|
A bus scan (needs rw-permissions to see a drive):
|
||||||
|
test/libburner --drive -
|
||||||
|
Burn a file to drive chosen by number:
|
||||||
|
test/libburner --drive 0 --burn_for_real my_image_file
|
||||||
|
Burn a file to drive chosen by persistent address:
|
||||||
|
test/libburner --drive /dev/hdc --burn_for_real my_image_file
|
||||||
|
Blank a used CD-RW (is combinable with burning in one run):
|
||||||
|
test/libburner --drive 0 --blank_fast
|
||||||
|
Burn a compressed afio archive on-the-fly, pad up to 700 MB:
|
||||||
|
( cd my_directory ; find . -print | afio -oZ - ) | \
|
||||||
|
test/libburner --drive /dev/hdc --burn_for_real --stdin_size 734003200 -
|
||||||
|
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.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
@subsection libburner-source Sourceode of libburner
|
||||||
|
|
||||||
|
Click on blue names of functions, structures, variables, etc in oder to
|
||||||
|
get to the according specs of libburn API or libburner sourcecode.
|
||||||
|
|
||||||
|
@include libburner.c
|
||||||
|
*/
|
966
doc/cookbook.txt
966
doc/cookbook.txt
@ -1,966 +0,0 @@
|
|||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
114
libburn/async.c
114
libburn/async.c
@ -7,11 +7,9 @@
|
|||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "async.h"
|
#include "async.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "back_hacks.h"
|
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include <a ssert.h>
|
#include <a ssert.h>
|
||||||
@ -37,14 +35,6 @@ struct erase_opts
|
|||||||
int fast;
|
int fast;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ts A61230 */
|
|
||||||
struct format_opts
|
|
||||||
{
|
|
||||||
struct burn_drive *drive;
|
|
||||||
off_t size;
|
|
||||||
int flag;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct write_opts
|
struct write_opts
|
||||||
{
|
{
|
||||||
struct burn_drive *drive;
|
struct burn_drive *drive;
|
||||||
@ -52,7 +42,6 @@ struct write_opts
|
|||||||
struct burn_disc *disc;
|
struct burn_disc *disc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct w_list
|
struct w_list
|
||||||
{
|
{
|
||||||
struct burn_drive *drive;
|
struct burn_drive *drive;
|
||||||
@ -64,7 +53,6 @@ struct w_list
|
|||||||
{
|
{
|
||||||
struct scan_opts scan;
|
struct scan_opts scan;
|
||||||
struct erase_opts erase;
|
struct erase_opts erase;
|
||||||
struct format_opts format;
|
|
||||||
struct write_opts write;
|
struct write_opts write;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
@ -210,9 +198,6 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
|
|||||||
{
|
{
|
||||||
struct erase_opts o;
|
struct erase_opts o;
|
||||||
|
|
||||||
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
|
|
||||||
drive->cancel = 1;
|
|
||||||
|
|
||||||
/* ts A61006 */
|
/* ts A61006 */
|
||||||
/* a ssert(drive); */
|
/* a ssert(drive); */
|
||||||
/* a ssert(!SCAN_GOING()); */
|
/* a ssert(!SCAN_GOING()); */
|
||||||
@ -233,83 +218,11 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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) ||
|
|
||||||
drive->current_profile == 0x13 ) ) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
|
||||||
0x00020130,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"Drive and media state unsuitable for blanking",
|
|
||||||
0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
o.drive = drive;
|
o.drive = drive;
|
||||||
o.fast = fast;
|
o.fast = fast;
|
||||||
add_worker(drive, (WorkerFunc) erase_worker_func, &o);
|
add_worker(drive, (WorkerFunc) erase_worker_func, &o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61230 */
|
|
||||||
static void *format_worker_func(struct w_list *w)
|
|
||||||
{
|
|
||||||
burn_disc_format_sync(w->u.format.drive, w->u.format.size,
|
|
||||||
w->u.format.flag);
|
|
||||||
remove_worker(pthread_self());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61230 */
|
|
||||||
void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
|
|
||||||
{
|
|
||||||
struct format_opts o;
|
|
||||||
int ok = 0;
|
|
||||||
char msg[160];
|
|
||||||
|
|
||||||
if ((SCAN_GOING()) || find_worker(drive)) {
|
|
||||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
|
||||||
0x00020102,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
"A drive operation is still going on (want to format)",
|
|
||||||
0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (flag & 128) /* application prescribed format type */
|
|
||||||
flag |= 16; /* enforce re-format */
|
|
||||||
|
|
||||||
if (drive->current_profile == 0x14)
|
|
||||||
ok = 1; /* DVD-RW sequential */
|
|
||||||
else if (drive->current_profile == 0x13 && (flag & 16))
|
|
||||||
ok = 1; /* DVD-RW Restricted Overwrite with force bit */
|
|
||||||
else if (drive->current_profile == 0x1a) {
|
|
||||||
ok = 1; /* DVD+RW */
|
|
||||||
size = 0;
|
|
||||||
flag &= ~(2|8); /* no insisting in size 0, no expansion */
|
|
||||||
flag |= 4; /* format up to maximum size */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
sprintf(msg,"Will not format media type %4.4Xh",
|
|
||||||
drive->current_profile);
|
|
||||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
|
||||||
0x00020129,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0, 0);
|
|
||||||
drive->cancel = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
o.drive = drive;
|
|
||||||
o.size = size;
|
|
||||||
o.flag = flag;
|
|
||||||
add_worker(drive, (WorkerFunc) format_worker_func, &o);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void *write_disc_worker_func(struct w_list *w)
|
static void *write_disc_worker_func(struct w_list *w)
|
||||||
{
|
{
|
||||||
burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
|
burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
|
||||||
@ -325,14 +238,6 @@ static void *write_disc_worker_func(struct w_list *w)
|
|||||||
void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
|
void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
|
||||||
{
|
{
|
||||||
struct write_opts o;
|
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 */
|
/* ts A61006 */
|
||||||
/* a ssert(!SCAN_GOING()); */
|
/* a ssert(!SCAN_GOING()); */
|
||||||
@ -357,25 +262,6 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
|
|||||||
if (! burn_disc_write_is_ok(opts, disc)) /* issues own msgs */
|
if (! burn_disc_write_is_ok(opts, disc)) /* issues own msgs */
|
||||||
return;
|
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.drive = opts->drive;
|
||||||
o.opts = opts;
|
o.opts = opts;
|
||||||
o.disc = disc;
|
o.disc = disc;
|
||||||
|
@ -63,9 +63,9 @@ static int signal_list_count= 24;
|
|||||||
|
|
||||||
/* Signals not to be caught */
|
/* Signals not to be caught */
|
||||||
static int non_signal_list[]= {
|
static int non_signal_list[]= {
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1
|
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, -1
|
||||||
};
|
};
|
||||||
static int non_signal_list_count= 5;
|
static int non_signal_list_count= 4;
|
||||||
|
|
||||||
|
|
||||||
#endif /* Cleanup_has_no_libburn_os_H */
|
#endif /* Cleanup_has_no_libburn_os_H */
|
||||||
@ -75,7 +75,6 @@ static int non_signal_list_count= 5;
|
|||||||
/* run time dynamic part */
|
/* run time dynamic part */
|
||||||
static char cleanup_msg[4096]= {""};
|
static char cleanup_msg[4096]= {""};
|
||||||
static int cleanup_exiting= 0;
|
static int cleanup_exiting= 0;
|
||||||
static int cleanup_has_reported= -1234567890;
|
|
||||||
|
|
||||||
static void *cleanup_app_handle= NULL;
|
static void *cleanup_app_handle= NULL;
|
||||||
static Cleanup_app_handler_T cleanup_app_handler= NULL;
|
static Cleanup_app_handler_T cleanup_app_handler= NULL;
|
||||||
@ -86,10 +85,8 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) {
|
if(cleanup_msg[0]!=0)
|
||||||
fprintf(stderr,"\n%s\n",cleanup_msg);
|
fprintf(stderr,"\n%s\n",cleanup_msg);
|
||||||
cleanup_has_reported= signum;
|
|
||||||
}
|
|
||||||
if(cleanup_perform_app_handler_first)
|
if(cleanup_perform_app_handler_first)
|
||||||
if(cleanup_app_handler!=NULL) {
|
if(cleanup_app_handler!=NULL) {
|
||||||
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
|
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
|
||||||
|
605
libburn/drive.c
605
libburn/drive.c
@ -25,9 +25,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "sg.h"
|
#include "sg.h"
|
||||||
#include "structure.h"
|
#include "structure.h"
|
||||||
|
#include "back_hacks.h"
|
||||||
/* ts A70107 : to get BE_CANCELLED */
|
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
#include "libdax_msgs.h"
|
#include "libdax_msgs.h"
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
extern struct libdax_msgs *libdax_messenger;
|
||||||
@ -56,7 +54,6 @@ void burn_drive_free(struct burn_drive *d)
|
|||||||
if (burn_drive_is_open(d))
|
if (burn_drive_is_open(d))
|
||||||
d->release(d);
|
d->release(d);
|
||||||
free((void *) d->idata);
|
free((void *) d->idata);
|
||||||
burn_mdata_free_subs(d->mdata);
|
|
||||||
free((void *) d->mdata);
|
free((void *) d->mdata);
|
||||||
if(d->toc_entry != NULL)
|
if(d->toc_entry != NULL)
|
||||||
free((void *) d->toc_entry);
|
free((void *) d->toc_entry);
|
||||||
@ -138,39 +135,54 @@ unsigned int burn_drive_count(void)
|
|||||||
return drivetop + 1;
|
return drivetop + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int burn_drive_grab(struct burn_drive *d, int le)
|
||||||
/* ts A61125 : media status aspects of burn_drive_grab() */
|
|
||||||
int burn_drive_inquire_media(struct burn_drive *d)
|
|
||||||
{
|
{
|
||||||
|
int errcode;
|
||||||
|
int was_equal = 0, must_equal = 3, max_loop = 20;
|
||||||
|
|
||||||
/* ts A61225 : after loading the tray, mode page 2Ah can change */
|
/* ts A60907 */
|
||||||
d->getcaps(d);
|
int loop_count, old_speed = -1234567890, new_speed = -987654321;
|
||||||
|
int old_erasable = -1234567890, new_erasable = -987654321;
|
||||||
|
|
||||||
/* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */
|
if (!d->released) {
|
||||||
|
burn_print(1, "can't grab - already grabbed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
errcode = d->grab(d);
|
||||||
|
|
||||||
|
if (errcode == 0) {
|
||||||
|
burn_print(1, "low level drive grab failed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
d->busy = BURN_DRIVE_GRABBING;
|
||||||
|
|
||||||
|
if (le)
|
||||||
|
d->load(d);
|
||||||
|
|
||||||
|
d->lock(d);
|
||||||
|
d->start_unit(d);
|
||||||
|
|
||||||
|
/* ts A61020 : this was BURN_DISC_BLANK as pure guess */
|
||||||
|
d->status = BURN_DISC_UNREADY;
|
||||||
|
|
||||||
if (d->mdata->cdr_write || d->mdata->cdrw_write ||
|
if (d->mdata->cdr_write || d->mdata->cdrw_write ||
|
||||||
d->mdata->dvdr_write || d->mdata->dvdram_write) {
|
d->mdata->dvdr_write || d->mdata->dvdram_write) {
|
||||||
|
|
||||||
#define Libburn_knows_correct_state_after_loaD 1
|
#ifdef Libburn_grab_release_and_grab_agaiN
|
||||||
#ifdef Libburn_knows_correct_state_after_loaD
|
|
||||||
|
|
||||||
d->read_disc_info(d);
|
d->read_disc_info(d);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* ts A61227 : This repeated read_disc_info seems
|
|
||||||
to be obsoleted by above d->getcaps(d).
|
|
||||||
*/
|
|
||||||
/* ts A60908 */
|
/* ts A60908 */
|
||||||
/* Trying to stabilize the disc status after eventual load
|
/* Trying to stabilize the disc status after eventual load
|
||||||
without closing and re-opening the drive */
|
without closing and re-opening the drive */
|
||||||
/* This seems to work for burn_disc_erasable() .
|
/* This seems to work for burn_disc_erasable() .
|
||||||
Speed values on RIP-14 and LITE-ON 48125S are stable
|
Speed values on RIP-14 and LITE-ON 48125S are stable
|
||||||
and false, nevertheless. */
|
and false, nevertheless. So cdrskin -atip is still
|
||||||
int was_equal = 0, must_equal = 3, max_loop = 20;
|
forced to finish-initialize. */
|
||||||
int loop_count, old_speed = -1234567890, new_speed= -987654321;
|
/*
|
||||||
int old_erasable = -1234567890, new_erasable = -987654321;
|
fprintf(stderr,"libburn: experimental: read_disc_info()\n");
|
||||||
|
*/
|
||||||
fprintf(stderr,"LIBBURN_DEBUG: read_disc_info()\n");
|
|
||||||
for (loop_count = 0; loop_count < max_loop; loop_count++){
|
for (loop_count = 0; loop_count < max_loop; loop_count++){
|
||||||
old_speed = new_speed;
|
old_speed = new_speed;
|
||||||
old_erasable = new_erasable;
|
old_erasable = new_erasable;
|
||||||
@ -190,57 +202,18 @@ int burn_drive_inquire_media(struct burn_drive *d)
|
|||||||
was_equal = 0;
|
was_equal = 0;
|
||||||
/*
|
/*
|
||||||
if (loop_count >= 1 && was_equal == 0)
|
if (loop_count >= 1 && was_equal == 0)
|
||||||
*/
|
fprintf(stderr,"libburn: experimental: %d : speed %d:%d erasable %d:%d\n",
|
||||||
fprintf(stderr,"LIBBURN_DEBUG: %d : speed %d:%d erasable %d:%d\n",
|
|
||||||
loop_count,old_speed,new_speed,old_erasable,new_erasable);
|
loop_count,old_speed,new_speed,old_erasable,new_erasable);
|
||||||
|
*/
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
}
|
}
|
||||||
#endif /* ! Libburn_knows_correct_state_after_loaD */
|
#endif /* ! Libburn_grab_release_and_grab_agaiN */
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (d->current_profile == -1 || d->current_is_cd_profile)
|
|
||||||
d->read_toc(d);
|
d->read_toc(d);
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int burn_drive_grab(struct burn_drive *d, int le)
|
|
||||||
{
|
|
||||||
int errcode;
|
|
||||||
/* ts A61125 - A61202 */
|
|
||||||
int ret, sose;
|
|
||||||
|
|
||||||
if (!d->released) {
|
|
||||||
burn_print(1, "can't grab - already grabbed\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
d->status = BURN_DISC_UNREADY;
|
|
||||||
errcode = d->grab(d);
|
|
||||||
|
|
||||||
if (errcode == 0) {
|
|
||||||
burn_print(1, "low level drive grab failed\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
d->busy = BURN_DRIVE_GRABBING;
|
|
||||||
|
|
||||||
if (le)
|
|
||||||
d->load(d);
|
|
||||||
|
|
||||||
d->lock(d);
|
|
||||||
|
|
||||||
/* ts A61118 */
|
|
||||||
d->start_unit(d);
|
|
||||||
|
|
||||||
/* ts A61202 : gave bit1 of le a meaning */
|
|
||||||
sose = d->silent_on_scsi_error;
|
|
||||||
if (!le)
|
|
||||||
d->silent_on_scsi_error = 1;
|
|
||||||
/* ts A61125 : outsourced media state inquiry aspects */
|
|
||||||
ret = burn_drive_inquire_media(d);
|
|
||||||
d->silent_on_scsi_error = sose;
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
d->busy = BURN_DRIVE_IDLE;
|
||||||
return ret;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct burn_drive *burn_drive_register(struct burn_drive *d)
|
struct burn_drive *burn_drive_register(struct burn_drive *d)
|
||||||
@ -338,31 +311,6 @@ struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61125 : model aspects of burn_drive_release */
|
|
||||||
int burn_drive_mark_unready(struct burn_drive *d)
|
|
||||||
{
|
|
||||||
/* ts A61020 : mark media info as invalid */
|
|
||||||
d->start_lba= -2000000000;
|
|
||||||
d->end_lba= -2000000000;
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
d->toc_entry = NULL;
|
|
||||||
d->toc_entries = 0;
|
|
||||||
if (d->disc != NULL) {
|
|
||||||
burn_disc_free(d->disc);
|
|
||||||
d->disc = NULL;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void burn_drive_release(struct burn_drive *d, int le)
|
void burn_drive_release(struct burn_drive *d, int le)
|
||||||
{
|
{
|
||||||
if (d->released) {
|
if (d->released) {
|
||||||
@ -386,14 +334,26 @@ void burn_drive_release(struct burn_drive *d, int le)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ts A61020 : mark media info as invalid */
|
||||||
|
d->start_lba= -2000000000;
|
||||||
|
d->end_lba= -2000000000;
|
||||||
|
|
||||||
d->unlock(d);
|
d->unlock(d);
|
||||||
if (le)
|
if (le)
|
||||||
d->eject(d);
|
d->eject(d);
|
||||||
d->release(d);
|
|
||||||
d->released = 1;
|
|
||||||
|
|
||||||
/* ts A61125 : outsourced model aspects */
|
d->release(d);
|
||||||
burn_drive_mark_unready(d);
|
|
||||||
|
d->status = BURN_DISC_UNREADY;
|
||||||
|
d->released = 1;
|
||||||
|
if (d->toc_entry != NULL)
|
||||||
|
free(d->toc_entry);
|
||||||
|
d->toc_entry = NULL;
|
||||||
|
d->toc_entries = 0;
|
||||||
|
if (d->disc != NULL) {
|
||||||
|
burn_disc_free(d->disc);
|
||||||
|
d->disc = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -449,6 +409,11 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
|
|||||||
burn_print(1, "erasing drive %s %s\n", d->idata->vendor,
|
burn_print(1, "erasing drive %s %s\n", d->idata->vendor,
|
||||||
d->idata->product);
|
d->idata->product);
|
||||||
|
|
||||||
|
/* ts A60825 : allow on parole to blank appendable CDs */
|
||||||
|
if ( ! (d->status == BURN_DISC_FULL ||
|
||||||
|
(d->status == BURN_DISC_APPENDABLE &&
|
||||||
|
! libburn_back_hack_42) ) )
|
||||||
|
return;
|
||||||
d->cancel = 0;
|
d->cancel = 0;
|
||||||
d->busy = BURN_DRIVE_ERASING;
|
d->busy = BURN_DRIVE_ERASING;
|
||||||
d->erase(d, fast);
|
d->erase(d, fast);
|
||||||
@ -469,144 +434,9 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
|
|||||||
!d->test_unit_ready(d))
|
!d->test_unit_ready(d))
|
||||||
sleep(1);
|
sleep(1);
|
||||||
d->progress.sector = 0x10000;
|
d->progress.sector = 0x10000;
|
||||||
|
|
||||||
/* ts A61125 : update media state records */
|
|
||||||
burn_drive_mark_unready(d);
|
|
||||||
burn_drive_inquire_media(d);
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
d->busy = BURN_DRIVE_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
@param flag: bit0 = fill formatted size with zeros
|
|
||||||
bit1, bit2 , bit4, bit7 - bit15 are for d->format_unit()
|
|
||||||
*/
|
|
||||||
void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
|
|
||||||
{
|
|
||||||
int ret, buf_secs, err, i, stages = 1, pbase, pfill, pseudo_sector;
|
|
||||||
off_t num_bufs;
|
|
||||||
char msg[80];
|
|
||||||
struct buffer buf;
|
|
||||||
|
|
||||||
/* reset the progress */
|
|
||||||
d->progress.session = 0;
|
|
||||||
d->progress.sessions = 1;
|
|
||||||
d->progress.track = 0;
|
|
||||||
d->progress.tracks = 1;
|
|
||||||
d->progress.index = 0;
|
|
||||||
d->progress.indices = 1;
|
|
||||||
d->progress.start_sector = 0;
|
|
||||||
d->progress.sectors = 0x10000;
|
|
||||||
d->progress.sector = 0;
|
|
||||||
stages = 1 + ((flag & 1) && size > 1024 * 1024);
|
|
||||||
d->cancel = 0;
|
|
||||||
d->busy = BURN_DRIVE_FORMATTING;
|
|
||||||
ret = d->format_unit(d, size, flag & 0xff96); /* forward bits */
|
|
||||||
if (ret <= 0)
|
|
||||||
d->cancel = 1;
|
|
||||||
|
|
||||||
while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0)
|
|
||||||
sleep(1);
|
|
||||||
while ((pseudo_sector = d->get_erase_progress(d)) > 0 ||
|
|
||||||
!d->test_unit_ready(d)) {
|
|
||||||
d->progress.sector = pseudo_sector / stages;
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
d->sync_cache(d);
|
|
||||||
|
|
||||||
if (size <= 0)
|
|
||||||
goto ex;
|
|
||||||
|
|
||||||
/* update media state records */
|
|
||||||
burn_drive_mark_unready(d);
|
|
||||||
burn_drive_inquire_media(d);
|
|
||||||
if (flag & 1) {
|
|
||||||
/* write size in zeros */;
|
|
||||||
pbase = 0x8000 + 0x7fff * (stages == 1);
|
|
||||||
pfill = 0xffff - pbase;
|
|
||||||
buf_secs = 16; /* Must not be more than 16 */
|
|
||||||
num_bufs = size / buf_secs / 2048;
|
|
||||||
if (num_bufs > 0x7fffffff) {
|
|
||||||
d->cancel = 1;
|
|
||||||
goto ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* <<< */
|
|
||||||
sprintf(msg,
|
|
||||||
"Writing %.f sectors of zeros to formatted media",
|
|
||||||
(double) num_bufs * (double) buf_secs);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00000002,
|
|
||||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
|
||||||
msg, 0, 0);
|
|
||||||
|
|
||||||
d->buffer = &buf;
|
|
||||||
memset(d->buffer, 0, sizeof(struct buffer));
|
|
||||||
d->buffer->bytes = buf_secs * 2048;
|
|
||||||
d->buffer->sectors = buf_secs;
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
for (i = 0; i < num_bufs; i++) {
|
|
||||||
d->nwa = i * buf_secs;
|
|
||||||
err = d->write(d, d->nwa, d->buffer);
|
|
||||||
if (err == BE_CANCELLED || d->cancel) {
|
|
||||||
d->cancel = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
d->progress.sector = pbase
|
|
||||||
+ pfill * ((double) i / (double) num_bufs);
|
|
||||||
}
|
|
||||||
d->sync_cache(d);
|
|
||||||
if (d->current_profile == 0x13 || d->current_profile == 0x1a) {
|
|
||||||
/* DVD-RW or DVD+RW */
|
|
||||||
d->busy = BURN_DRIVE_CLOSING_SESSION;
|
|
||||||
/* CLOSE SESSION, 010b */
|
|
||||||
d->close_track_session(d, 1, 0);
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ex:;
|
|
||||||
d->progress.sector = 0x10000;
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
|
||||||
d->buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A70112 API */
|
|
||||||
int burn_disc_get_formats(struct burn_drive *d, int *status, off_t *size,
|
|
||||||
unsigned *bl_sas, int *num_formats)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
*status = 0;
|
|
||||||
*size = 0;
|
|
||||||
*bl_sas = 0;
|
|
||||||
*num_formats = 0;
|
|
||||||
ret = d->read_format_capacities(d, 0x00);
|
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
|
||||||
*status = d->format_descr_type;
|
|
||||||
*size = d->format_curr_max_size;
|
|
||||||
*bl_sas = d->format_curr_blsas;
|
|
||||||
*num_formats = d->num_format_descr;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A70112 API */
|
|
||||||
int burn_disc_get_format_descr(struct burn_drive *d, int index,
|
|
||||||
int *type, off_t *size, unsigned *tdp)
|
|
||||||
{
|
|
||||||
*type = 0;
|
|
||||||
*size = 0;
|
|
||||||
*tdp = 0;
|
|
||||||
if (index < 0 || index >= d->num_format_descr)
|
|
||||||
return 0;
|
|
||||||
*type = d->format_descriptors[index].type;
|
|
||||||
*size = d->format_descriptors[index].size;
|
|
||||||
*tdp = d->format_descriptors[index].tdp;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
enum burn_disc_status burn_disc_get_status(struct burn_drive *d)
|
enum burn_disc_status burn_disc_get_status(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
/* ts A61007 */
|
/* ts A61007 */
|
||||||
@ -1185,7 +1015,7 @@ int burn_drive_find_scsi_equiv(char *path, char adr[])
|
|||||||
ret = burn_drive_obtain_scsi_adr(path, &bus_no, &host_no, &channel_no,
|
ret = burn_drive_obtain_scsi_adr(path, &bus_no, &host_no, &channel_no,
|
||||||
&target_no, &lun_no);
|
&target_no, &lun_no);
|
||||||
if(ret <= 0) {
|
if(ret <= 0) {
|
||||||
sprintf(msg,"burn_drive_obtain_scsi_adr( %s ) returns %d",
|
sprintf(msg,"burn_drive_obtain_scsi_adr( %s ) returns %d\n",
|
||||||
path, ret);
|
path, ret);
|
||||||
burn_drive_adr_debug_msg(msg, NULL);
|
burn_drive_adr_debug_msg(msg, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1272,7 +1102,7 @@ int burn_abort_pacifier(void *handle, int patience, int elapsed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Abort any running drive operation and finish libburn.
|
/** Abort any running drive operation and finis libburn.
|
||||||
@param patience Maximum number of seconds to wait for drives to finish
|
@param patience Maximum number of seconds to wait for drives to finish
|
||||||
@param pacifier_func Function to produce appeasing messages. See
|
@param pacifier_func Function to produce appeasing messages. See
|
||||||
burn_abort_pacifier() for an example.
|
burn_abort_pacifier() for an example.
|
||||||
@ -1370,13 +1200,8 @@ int burn_disc_read_atip(struct burn_drive *d)
|
|||||||
0, 0);
|
0, 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (d->current_profile == -1 || d->current_is_cd_profile) {
|
|
||||||
d->read_atip(d);
|
d->read_atip(d);
|
||||||
/* >>> some control of success would be nice :) */
|
/* >>> some control of success would be nice :) */
|
||||||
} else {
|
|
||||||
/* mmc5r03c.pdf 6.26.3.6.3 : ATIP is undefined for non-CD */;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1408,313 +1233,3 @@ int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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])
|
|
||||||
{
|
|
||||||
*pno = d->current_profile;
|
|
||||||
strcpy(name,d->current_profile_text);
|
|
||||||
return *pno >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61223 : New API function */
|
|
||||||
int burn_drive_wrote_well(struct burn_drive *d)
|
|
||||||
{
|
|
||||||
return !d->cancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
int burn_speed_descriptor_new(struct burn_speed_descriptor **s,
|
|
||||||
struct burn_speed_descriptor *prev,
|
|
||||||
struct burn_speed_descriptor *next, int flag)
|
|
||||||
{
|
|
||||||
struct burn_speed_descriptor *o;
|
|
||||||
|
|
||||||
(*s) = o = malloc(sizeof(struct burn_speed_descriptor));
|
|
||||||
if (o == NULL)
|
|
||||||
return -1;
|
|
||||||
o->source = 0;
|
|
||||||
o->profile_loaded = -2;
|
|
||||||
o->profile_name[0] = 0;
|
|
||||||
o->wrc = 0;
|
|
||||||
o->exact = 0;
|
|
||||||
o->mrw = 0;
|
|
||||||
o->end_lba = -1;
|
|
||||||
o->write_speed = 0;
|
|
||||||
o->read_speed = 0;
|
|
||||||
|
|
||||||
o->prev = prev;
|
|
||||||
if (prev != NULL) {
|
|
||||||
next = prev->next;
|
|
||||||
prev->next = o;
|
|
||||||
}
|
|
||||||
o->next = next;
|
|
||||||
if (next != NULL)
|
|
||||||
next->prev = o;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
/* @param flag bit0= destroy whole next-chain of descriptors */
|
|
||||||
int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag)
|
|
||||||
{
|
|
||||||
struct burn_speed_descriptor *next, *o;
|
|
||||||
|
|
||||||
if ((*s) == NULL)
|
|
||||||
return 0;
|
|
||||||
if (flag&1)
|
|
||||||
for (o = (*s); o->prev != NULL; o = o->prev);
|
|
||||||
else
|
|
||||||
o = (*s);
|
|
||||||
next = o->next;
|
|
||||||
if (next != NULL)
|
|
||||||
next->prev = o->prev;
|
|
||||||
if (o->prev != NULL)
|
|
||||||
o->prev->next = next;
|
|
||||||
free((char *) (*s));
|
|
||||||
(*s) = NULL;
|
|
||||||
if (flag&1)
|
|
||||||
return burn_speed_descriptor_destroy(&next, flag&1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
int burn_speed_descriptor_copy(struct burn_speed_descriptor *from,
|
|
||||||
struct burn_speed_descriptor *to, int flag)
|
|
||||||
{
|
|
||||||
to->source = from->source;
|
|
||||||
to->profile_loaded = from->profile_loaded;
|
|
||||||
strcpy(to->profile_name, from->profile_name);
|
|
||||||
to->wrc = from->wrc;
|
|
||||||
to->exact = from->exact;
|
|
||||||
to->mrw = from->mrw;
|
|
||||||
to->end_lba = from->end_lba;
|
|
||||||
to->write_speed = from->write_speed;
|
|
||||||
to->read_speed = from->read_speed;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
|
|
||||||
int burn_mdata_free_subs(struct scsi_mode_data *m)
|
|
||||||
{
|
|
||||||
burn_speed_descriptor_destroy(&(m->speed_descriptors), 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 : API function */
|
|
||||||
int burn_drive_get_speedlist(struct burn_drive *d,
|
|
||||||
struct burn_speed_descriptor **speed_list)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
struct burn_speed_descriptor *sd, *csd = NULL;
|
|
||||||
|
|
||||||
(*speed_list) = NULL;
|
|
||||||
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
|
|
||||||
ret = burn_speed_descriptor_new(&csd, NULL, csd, 0);
|
|
||||||
if (ret <= 0)
|
|
||||||
return -1;
|
|
||||||
burn_speed_descriptor_copy(sd, csd, 0);
|
|
||||||
}
|
|
||||||
(*speed_list) = csd;
|
|
||||||
return (csd != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 : API function */
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
struct burn_drive;
|
struct burn_drive;
|
||||||
struct command;
|
struct command;
|
||||||
struct mempage;
|
struct mempage;
|
||||||
struct scsi_mode_data;
|
|
||||||
struct burn_speed_descriptor;
|
|
||||||
|
|
||||||
#define LEAD_IN 1
|
#define LEAD_IN 1
|
||||||
#define GAP 2
|
#define GAP 2
|
||||||
@ -71,41 +69,5 @@ int burn_setup_drive(struct burn_drive *d, char *fname);
|
|||||||
*/
|
*/
|
||||||
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d);
|
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d);
|
||||||
|
|
||||||
/* ts A61125 : media status aspects of burn_drive_grab() */
|
|
||||||
int burn_drive_inquire_media(struct burn_drive *d);
|
|
||||||
|
|
||||||
/* ts A61125 : model aspects of burn_drive_release */
|
|
||||||
int burn_drive_mark_unready(struct burn_drive *d);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
int burn_speed_descriptor_new(struct burn_speed_descriptor **s,
|
|
||||||
struct burn_speed_descriptor *prev,
|
|
||||||
struct burn_speed_descriptor *next, int flag);
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
/* @param flag bit0= destroy whole next-chain of descriptors */
|
|
||||||
int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
|
|
||||||
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 */
|
#endif /* __DRIVE */
|
||||||
|
@ -42,7 +42,7 @@ static int file_read(struct burn_source *source,
|
|||||||
unsigned char *buffer,
|
unsigned char *buffer,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
struct burn_source_file *fs = source->data;
|
struct burn_source_fd *fs = source->data;
|
||||||
|
|
||||||
return read_full_buffer(fs->datafd, buffer, size);
|
return read_full_buffer(fs->datafd, buffer, size);
|
||||||
}
|
}
|
||||||
@ -71,24 +71,14 @@ static off_t file_size(struct burn_source *source)
|
|||||||
struct stat buf;
|
struct stat buf;
|
||||||
struct burn_source_file *fs = source->data;
|
struct burn_source_file *fs = source->data;
|
||||||
|
|
||||||
if (fs->fixed_size > 0)
|
|
||||||
return fs->fixed_size;
|
|
||||||
if (fstat(fs->datafd, &buf) == -1)
|
if (fstat(fs->datafd, &buf) == -1)
|
||||||
return (off_t) 0;
|
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;
|
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 *burn_file_source_new(const char *path, const char *subpath)
|
||||||
{
|
{
|
||||||
struct burn_source_file *fs;
|
struct burn_source_file *fs;
|
||||||
@ -113,43 +103,84 @@ struct burn_source *burn_file_source_new(const char *path, const char *subpath)
|
|||||||
if (subpath)
|
if (subpath)
|
||||||
fs->subfd = fd2;
|
fs->subfd = fd2;
|
||||||
|
|
||||||
/* ts A70125 */
|
|
||||||
fs->fixed_size = 0;
|
|
||||||
|
|
||||||
src = burn_source_new();
|
src = burn_source_new();
|
||||||
src->read = file_read;
|
src->read = file_read;
|
||||||
if (subpath)
|
if (subpath)
|
||||||
src->read_sub = file_read_sub;
|
src->read_sub = file_read_sub;
|
||||||
|
|
||||||
src->get_size = file_size;
|
src->get_size = file_size;
|
||||||
src->set_size = file_set_size;
|
|
||||||
src->free_data = file_free;
|
src->free_data = file_free;
|
||||||
src->data = fs;
|
src->data = fs;
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A70126 : removed class burn_source_fd in favor of burn_source_file */
|
/* ------ 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
|
struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
|
||||||
{
|
{
|
||||||
struct burn_source_file *fs;
|
struct burn_source_fd *fs;
|
||||||
struct burn_source *src;
|
struct burn_source *src;
|
||||||
|
|
||||||
if (datafd == -1)
|
if (datafd == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
fs = malloc(sizeof(struct burn_source_file));
|
fs = malloc(sizeof(struct burn_source_fd));
|
||||||
fs->datafd = datafd;
|
fs->datafd = datafd;
|
||||||
fs->subfd = subfd;
|
fs->subfd = subfd;
|
||||||
fs->fixed_size = size;
|
fs->fixed_size = size;
|
||||||
|
|
||||||
src = burn_source_new();
|
src = burn_source_new();
|
||||||
src->read = file_read;
|
src->read = fd_read;
|
||||||
if(subfd != -1)
|
if(subfd != -1)
|
||||||
src->read = file_read_sub;
|
src->read = fd_read_sub;
|
||||||
src->get_size = file_size;
|
src->get_size = fd_get_size;
|
||||||
src->set_size = file_set_size;
|
src->free_data = fd_free_data;
|
||||||
src->free_data = file_free;
|
|
||||||
src->data = fs;
|
src->data = fs;
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,16 @@ struct burn_source_file
|
|||||||
{
|
{
|
||||||
int datafd;
|
int datafd;
|
||||||
int subfd;
|
int subfd;
|
||||||
off_t fixed_size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ts A70126 : burn_source_file obsoleted burn_source_fd */
|
/* ------ provisory location for the new source subclass fd --------- */
|
||||||
|
|
||||||
|
struct burn_source_fd
|
||||||
|
{
|
||||||
|
int datafd;
|
||||||
|
int subfd;
|
||||||
|
off_t fixed_size;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* LIBBURN__FILE_H */
|
#endif /* LIBBURN__FILE_H */
|
||||||
|
@ -209,38 +209,8 @@ ex:
|
|||||||
|
|
||||||
int burn_builtin_abort_handler(void *handle, int signum, int flag)
|
int burn_builtin_abort_handler(void *handle, int signum, int flag)
|
||||||
{
|
{
|
||||||
if(getpid() != abort_control_pid) {
|
if(getpid() != abort_control_pid)
|
||||||
|
|
||||||
#ifdef Not_yeT
|
|
||||||
pthread_t thread_id;
|
|
||||||
|
|
||||||
/* >>> need better handling of self-induced SIGs
|
|
||||||
like SIGSEGV or SIGFPE.
|
|
||||||
Like bonking the control thread if it did not show up
|
|
||||||
after a short while.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* >>> if this is a non-fatal signal : return -2 */
|
|
||||||
|
|
||||||
thread_id = pthread_self();
|
|
||||||
/* >>> find thread_id in worker list of async.c */
|
|
||||||
/* >>> if owning a drive : mark idle and canceled
|
|
||||||
(can't do anything more) */
|
|
||||||
|
|
||||||
usleep(1000000); /* calm down */
|
|
||||||
|
|
||||||
/* forward signal to control thread */
|
|
||||||
if (abort_control_pid>1)
|
|
||||||
kill(abort_control_pid, signum);
|
|
||||||
|
|
||||||
/* >>> ??? end thread */;
|
|
||||||
|
|
||||||
#else
|
|
||||||
usleep(1000000); /* calm down */
|
|
||||||
return -2;
|
return -2;
|
||||||
#endif /* ! Not_yeT */
|
|
||||||
|
|
||||||
}
|
|
||||||
Cleanup_set_handlers(NULL, NULL, 2);
|
Cleanup_set_handlers(NULL, NULL, 2);
|
||||||
fprintf(stderr,"%sABORT : Trying to shut down drive and library\n",
|
fprintf(stderr,"%sABORT : Trying to shut down drive and library\n",
|
||||||
abort_message_prefix);
|
abort_message_prefix);
|
||||||
|
@ -107,40 +107,22 @@ struct burn_write_opts;
|
|||||||
enum burn_write_types
|
enum burn_write_types
|
||||||
{
|
{
|
||||||
/** Packet writing.
|
/** Packet writing.
|
||||||
currently unsupported, (for DVD Incremental Streaming use TAO)
|
currently unsupported
|
||||||
*/
|
*/
|
||||||
BURN_WRITE_PACKET,
|
BURN_WRITE_PACKET,
|
||||||
|
/** Track At Once recording.
|
||||||
/** With CD: Track At Once recording
|
|
||||||
2s gaps between tracks, no fonky lead-ins
|
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,
|
BURN_WRITE_TAO,
|
||||||
|
/** Session At Once.
|
||||||
/** With CD: Session At Once
|
block type MUST be BURN_BLOCK_SAO
|
||||||
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,
|
BURN_WRITE_SAO,
|
||||||
|
/** Raw disc at once recording.
|
||||||
/** With CD: Raw disc at once recording.
|
|
||||||
all subcodes must be provided by lib or user
|
all subcodes must be provided by lib or user
|
||||||
only raw block types are supported
|
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 */
|
/** Data format to send to the drive */
|
||||||
@ -247,26 +229,13 @@ enum burn_drive_status
|
|||||||
/** The drive is told to close a track (TAO only) */
|
/** The drive is told to close a track (TAO only) */
|
||||||
BURN_DRIVE_CLOSING_TRACK,
|
BURN_DRIVE_CLOSING_TRACK,
|
||||||
/** The drive is told to close a session (TAO only) */
|
/** The drive is told to close a session (TAO only) */
|
||||||
BURN_DRIVE_CLOSING_SESSION,
|
BURN_DRIVE_CLOSING_SESSION
|
||||||
|
|
||||||
/* ts A61223 */
|
|
||||||
/** The drive is formatting media */
|
|
||||||
BURN_DRIVE_FORMATTING
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Information about a track on a disc - this is from the q sub channel of the
|
/** 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.
|
lead-in area of a disc. The documentation here is very terse.
|
||||||
See a document such as mmc3 for proper information.
|
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
|
struct burn_toc_entry
|
||||||
{
|
{
|
||||||
@ -290,23 +259,6 @@ struct burn_toc_entry
|
|||||||
unsigned char psec;
|
unsigned char psec;
|
||||||
/** Track start time frames for normal tracks */
|
/** Track start time frames for normal tracks */
|
||||||
unsigned char pframe;
|
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;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -330,9 +282,6 @@ struct burn_source {
|
|||||||
/** Get the size of the source's data */
|
/** Get the size of the source's data */
|
||||||
off_t (*get_size)(struct burn_source *);
|
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 */
|
/** Clean up the source specific data */
|
||||||
void (*free_data)(struct burn_source *);
|
void (*free_data)(struct burn_source *);
|
||||||
|
|
||||||
@ -461,55 +410,6 @@ struct burn_progress {
|
|||||||
unsigned buffer_min_fill;
|
unsigned buffer_min_fill;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
/** Description of a speed capability as reported by the drive in conjunction
|
|
||||||
with eventually loaded media. There can be more than one such object per
|
|
||||||
drive. So they are chained via .next and .prev , where NULL marks the end
|
|
||||||
of the chain. This list is set up by burn_drive_scan() and gets updated
|
|
||||||
by burn_drive_grab().
|
|
||||||
A copy may be obtained by burn_drive_get_speedlist() and disposed by
|
|
||||||
burn_drive_free_speedlist().
|
|
||||||
For technical background info see SCSI specs MMC and SPC:
|
|
||||||
mode page 2Ah (from SPC 5Ah MODE SENSE) , mmc3r10g.pdf , 6.3.11 Table 364
|
|
||||||
ACh GET PERFORMANCE, Type 03h , mmc5r03c.pdf , 6.8.5.3 Table 312
|
|
||||||
*/
|
|
||||||
struct burn_speed_descriptor {
|
|
||||||
|
|
||||||
/** Where this info comes from :
|
|
||||||
0 = misc , 1 = mode page 2Ah , 2 = ACh GET PERFORMANCE */
|
|
||||||
int source;
|
|
||||||
|
|
||||||
/** The media type that was current at the time of report
|
|
||||||
-2 = state unknown, -1 = no media was loaded , else see
|
|
||||||
burn_disc_get_profile() */
|
|
||||||
int profile_loaded;
|
|
||||||
char profile_name[80];
|
|
||||||
|
|
||||||
/** The attributed capacity of appropriate media in logical block units
|
|
||||||
i.e. 2352 raw bytes or 2048 data bytes. -1 = capacity unknown. */
|
|
||||||
int end_lba;
|
|
||||||
|
|
||||||
/** Speed is given in 1000 bytes/s , 0 = invalid. The numbers
|
|
||||||
are supposed to be usable with burn_drive_set_speed() */
|
|
||||||
int write_speed;
|
|
||||||
int read_speed;
|
|
||||||
|
|
||||||
/** Expert info from ACh GET PERFORMANCE and/or mode page 2Ah.
|
|
||||||
Expect values other than 0 or 1 to get a meaning in future.*/
|
|
||||||
/* Rotational control: 0 = CLV/default , 1 = CAV */
|
|
||||||
int wrc;
|
|
||||||
/* 1 = drive promises reported performance over full media */
|
|
||||||
int exact;
|
|
||||||
/* 1 = suitable for mixture of read and write */
|
|
||||||
int mrw;
|
|
||||||
|
|
||||||
/** List chaining. Use .next until NULL to iterate over the list */
|
|
||||||
struct burn_speed_descriptor *prev;
|
|
||||||
struct burn_speed_descriptor *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** Initialize the library.
|
/** Initialize the library.
|
||||||
This must be called before using any other functions in the library. It
|
This must be called before using any other functions in the library. It
|
||||||
may be called more than once with no effect.
|
may be called more than once with no effect.
|
||||||
@ -541,7 +441,6 @@ void burn_finish(void);
|
|||||||
@param patience Maximum number of seconds to wait for drives to finish
|
@param patience Maximum number of seconds to wait for drives to finish
|
||||||
@param pacifier_func If not NULL: a function to produce appeasing messages.
|
@param pacifier_func If not NULL: a function to produce appeasing messages.
|
||||||
See burn_abort_pacifier() for an example.
|
See burn_abort_pacifier() for an example.
|
||||||
@param handle Opaque handle to be used with pacifier_func
|
|
||||||
@return 1 ok, all went well
|
@return 1 ok, all went well
|
||||||
0 had to leave a drive in unclean state
|
0 had to leave a drive in unclean state
|
||||||
<0 severe error, do no use libburn again
|
<0 severe error, do no use libburn again
|
||||||
@ -716,11 +615,6 @@ int burn_drive_convert_fs_adr(char *path, char adr[]);
|
|||||||
then it is not decisive and the first enumerated address which matches
|
then it is not decisive and the first enumerated address which matches
|
||||||
the >= 0 parameters is taken as result.
|
the >= 0 parameters is taken as result.
|
||||||
Note: bus and (host,channel) are supposed to be redundant.
|
Note: bus and (host,channel) are supposed to be redundant.
|
||||||
@param bus_no "Bus Number" (something like a virtual controller)
|
|
||||||
@param host_no "Host Number" (something like half a virtual controller)
|
|
||||||
@param channel_no "Channel Number" (other half of "Host Number")
|
|
||||||
@param target_no "Target Number" or "SCSI Id" (a device)
|
|
||||||
@param lun_no "Logical Unit Number" (a sub device)
|
|
||||||
@param adr An application provided array of at least BURN_DRIVE_ADR_LEN
|
@param adr An application provided array of at least BURN_DRIVE_ADR_LEN
|
||||||
characters size. The persistent address gets copied to it.
|
characters size. The persistent address gets copied to it.
|
||||||
@return 1 = success , 0 = failure , -1 = severe error
|
@return 1 = success , 0 = failure , -1 = severe error
|
||||||
@ -821,34 +715,11 @@ int burn_drive_get_start_end_lba(struct burn_drive *drive,
|
|||||||
@param d The drive to query.
|
@param d The drive to query.
|
||||||
@param o If not NULL: write parameters to be set on drive before query
|
@param o If not NULL: write parameters to be set on drive before query
|
||||||
@param trackno 0=next track to come, >0 number of existing track
|
@param trackno 0=next track to come, >0 number of existing track
|
||||||
@param lba return value: start lba
|
|
||||||
@param nwa return value: Next Writeable Address
|
|
||||||
@return 1=nwa is valid , 0=nwa is not valid , -1=error
|
@return 1=nwa is valid , 0=nwa is not valid , -1=error
|
||||||
*/
|
*/
|
||||||
int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
|
int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
|
||||||
int trackno, int *lba, int *nwa);
|
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.
|
|
||||||
libburn currently writes only to profiles 0x09 "CD-R", 0x0a "CD-RW",
|
|
||||||
0x12 "DVD-RAM", 0x13 "DVD-RW restricted overwrite" or 0x1a "DVD+RW".
|
|
||||||
@param d The drive where the media is inserted.
|
|
||||||
@param pno Profile Number as of mmc5r03c.pdf, table 89
|
|
||||||
@param name Profile Name (e.g "CD-RW", unknown profiles have empty name)
|
|
||||||
@return 1 profile is valid, 0 no profile info available
|
|
||||||
*/
|
|
||||||
int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80]);
|
|
||||||
|
|
||||||
/** Tells whether a disc can be erased or not
|
/** Tells whether a disc can be erased or not
|
||||||
@return Non-zero means erasable
|
@return Non-zero means erasable
|
||||||
@ -876,7 +747,7 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive);
|
|||||||
void burn_write_opts_free(struct burn_write_opts *opts);
|
void burn_write_opts_free(struct burn_write_opts *opts);
|
||||||
|
|
||||||
/** Creates a read_opts struct for reading from the specified drive
|
/** Creates a read_opts struct for reading from the specified drive
|
||||||
must be freed with burn_read_opts_free
|
must be freed with burn_write_opts_free
|
||||||
@param drive The drive to read from
|
@param drive The drive to read from
|
||||||
@return The read_opts
|
@return The read_opts
|
||||||
*/
|
*/
|
||||||
@ -898,79 +769,7 @@ void burn_read_opts_free(struct burn_read_opts *opts);
|
|||||||
*/
|
*/
|
||||||
void burn_disc_erase(struct burn_drive *drive, int fast);
|
void burn_disc_erase(struct burn_drive *drive, int fast);
|
||||||
|
|
||||||
|
/* ts A61109 : this is defunct */
|
||||||
/* ts A70101 - A70112 */
|
|
||||||
/** Format media for use with libburn. This currently applies to DVD-RW
|
|
||||||
in state "Sequential Recording" (profile 0014h) which get formatted to
|
|
||||||
state "Restricted Overwrite" (profile 0013h). DVD+RW can be "de-iced"
|
|
||||||
by setting bit2 of flag. Other media cannot be formatted yet.
|
|
||||||
@param drive The drive with the disc to format.
|
|
||||||
@param size The size in bytes to be used with the format command. It should
|
|
||||||
be divisible by 32*1024. The effect of this parameter may
|
|
||||||
depend on the media profile.
|
|
||||||
@param flag Bitfield for control purposes:
|
|
||||||
bit0= after formatting, write the given number of zero-bytes
|
|
||||||
to the media and eventually perform preliminary closing.
|
|
||||||
bit1= insist in size 0 even if there is a better default known
|
|
||||||
bit2= format to maximum available size
|
|
||||||
bit3= -reserved-
|
|
||||||
bit4= enforce re-format of (partly) formatted media
|
|
||||||
bit7= MMC expert application mode (else libburn tries to
|
|
||||||
choose a suitable format type):
|
|
||||||
bit8 to bit15 contain the index of the format to use. See
|
|
||||||
burn_disc_get_formats(), burn_disc_get_format_descr().
|
|
||||||
Acceptable types are: 0x00, 0x10, 0x11, 0x13, 0x15, 0x26.
|
|
||||||
If bit7 is set, bit4 is set automatically.
|
|
||||||
*/
|
|
||||||
void burn_disc_format(struct burn_drive *drive, off_t size, int flag);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A70112 */
|
|
||||||
/** Possible formatting status values */
|
|
||||||
#define BURN_FORMAT_IS_UNFORMATTED 1
|
|
||||||
#define BURN_FORMAT_IS_FORMATTED 2
|
|
||||||
#define BURN_FORMAT_IS_UNKNOWN 3
|
|
||||||
|
|
||||||
/** Inquire the formatting status, the associated sizes and the number of
|
|
||||||
available formats. The info is media specific and stems from MMC command
|
|
||||||
23h READ FORMAT CAPACITY. See mmc5r03c.pdf 6.24 for background details.
|
|
||||||
Media type can be determined via burn_disc_get_profile().
|
|
||||||
@param drive The drive with the disc to format.
|
|
||||||
@param status The current formatting status of the inserted media.
|
|
||||||
See BURN_FORMAT_IS_* macros. Note: "unknown" is the
|
|
||||||
legal status for quick formatted, yet unwritten DVD-RW.
|
|
||||||
@param size The size in bytes associated with status.
|
|
||||||
unformatted: the maximum achievable size of the media
|
|
||||||
formatted: the currently formatted capacity
|
|
||||||
unknown: maximum capacity of drive or of media
|
|
||||||
@param bl_sas Additional info "Block Length/Spare Area Size".
|
|
||||||
Expected to be constantly 2048 for non-BD media.
|
|
||||||
@param num_formats The number of available formats. To be used with
|
|
||||||
burn_disc_get_format_descr() to obtain such a format
|
|
||||||
and eventually with burn_disc_format() to select one.
|
|
||||||
@return 1 reply is valid , <=0 failure
|
|
||||||
*/
|
|
||||||
int burn_disc_get_formats(struct burn_drive *drive, int *status, off_t *size,
|
|
||||||
unsigned *bl_sas, int *num_formats);
|
|
||||||
|
|
||||||
/** Inquire parameters of an available media format.
|
|
||||||
@param drive The drive with the disc to format.
|
|
||||||
@param index The index of the format item. Beginning with 0 up to reply
|
|
||||||
parameter from burn_disc_get_formats() : num_formats - 1
|
|
||||||
@param type The format type. See mmc5r03c.pdf, 6.5, 04h FORMAT UNIT.
|
|
||||||
0x00=full, 0x10=CD-RW/DVD-RW full, 0x11=CD-RW/DVD-RW grow,
|
|
||||||
0x15=DVD-RW quick, 0x13=DVD-RW quick grow,
|
|
||||||
0x26=DVD+RW background
|
|
||||||
@param size The maximum size in bytes achievable with this format.
|
|
||||||
@param tdp Type Dependent Parameter. See mmc5r03c.pdf.
|
|
||||||
@return 1 reply is valid , <=0 failure
|
|
||||||
*/
|
|
||||||
int burn_disc_get_format_descr(struct burn_drive *drive, int index,
|
|
||||||
int *type, off_t *size, unsigned *tdp);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61109 : this was and is defunct */
|
|
||||||
/** Read a disc from the drive and write it to an fd pair. The drive must be
|
/** Read a disc from the drive and write it to an fd pair. The drive must be
|
||||||
grabbed successfully BEFORE calling this function. Always ensure that the
|
grabbed successfully BEFORE calling this function. Always ensure that the
|
||||||
drive reports a status of BURN_DISC_FULL before calling this function.
|
drive reports a status of BURN_DISC_FULL before calling this function.
|
||||||
@ -982,9 +781,6 @@ 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
|
/** 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
|
calling this function. Always ensure that the drive reports a status of
|
||||||
BURN_DISC_BLANK before calling this function.
|
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 o The options for the writing operation.
|
||||||
@param disc The struct burn_disc * that described the disc to be created
|
@param disc The struct burn_disc * that described the disc to be created
|
||||||
*/
|
*/
|
||||||
@ -997,17 +793,6 @@ void burn_disc_write(struct burn_write_opts *o, struct burn_disc *disc);
|
|||||||
*/
|
*/
|
||||||
void burn_drive_cancel(struct burn_drive *drive);
|
void burn_drive_cancel(struct burn_drive *drive);
|
||||||
|
|
||||||
|
|
||||||
/* ts A61223 */
|
|
||||||
/** Inquire wether the most recent write run was successful. Reasons for
|
|
||||||
non-success may be: rejection of burn parameters, abort during fatal errors
|
|
||||||
during write, a call to burn_drive_cancel() by the application thread.
|
|
||||||
@param d The drive to inquire.
|
|
||||||
@return 1=burn seems to have went well, 0=burn failed
|
|
||||||
*/
|
|
||||||
int burn_drive_wrote_well(struct burn_drive *d);
|
|
||||||
|
|
||||||
|
|
||||||
/** Convert a minute-second-frame (MSF) value to sector count
|
/** Convert a minute-second-frame (MSF) value to sector count
|
||||||
@param m Minute component
|
@param m Minute component
|
||||||
@param s Second component
|
@param s Second component
|
||||||
@ -1040,7 +825,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);
|
void burn_lba_to_msf(int lba, int *m, int *s, int *f);
|
||||||
|
|
||||||
/** Create a new disc */
|
/** Create a new disc (for DAO recording)*/
|
||||||
struct burn_disc *burn_disc_create(void);
|
struct burn_disc *burn_disc_create(void);
|
||||||
|
|
||||||
/** Delete disc and decrease the reference count on all its sessions
|
/** Delete disc and decrease the reference count on all its sessions
|
||||||
@ -1048,7 +833,9 @@ struct burn_disc *burn_disc_create(void);
|
|||||||
*/
|
*/
|
||||||
void burn_disc_free(struct burn_disc *d);
|
void burn_disc_free(struct burn_disc *d);
|
||||||
|
|
||||||
/** Create a new session */
|
/** Create a new session (For SAO at once recording, or to be added to a
|
||||||
|
disc for DAO)
|
||||||
|
*/
|
||||||
struct burn_session *burn_session_create(void);
|
struct burn_session *burn_session_create(void);
|
||||||
|
|
||||||
/** Free a session (and decrease reference count on all tracks inside)
|
/** Free a session (and decrease reference count on all tracks inside)
|
||||||
@ -1203,9 +990,7 @@ void burn_structure_print_disc(struct burn_disc *d);
|
|||||||
void burn_structure_print_session(struct burn_session *s);
|
void burn_structure_print_session(struct burn_session *s);
|
||||||
void burn_structure_print_track(struct burn_track *t);
|
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 opts The write opts to change
|
||||||
@param write_type The write type to use
|
@param write_type The write type to use
|
||||||
@param block_type The block type to use
|
@param block_type The block type to use
|
||||||
@ -1215,22 +1000,6 @@ int burn_write_opts_set_write_type(struct burn_write_opts *opts,
|
|||||||
enum burn_write_types write_type,
|
enum burn_write_types write_type,
|
||||||
int block_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
|
/** Supplies toc entries for writing - not normally required for cd mastering
|
||||||
@param opts The write opts to change
|
@param opts The write opts to change
|
||||||
@param count The number of entries
|
@param count The number of entries
|
||||||
@ -1275,26 +1044,13 @@ void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts, unsigned cha
|
|||||||
|
|
||||||
|
|
||||||
/* ts A61106 */
|
/* ts A61106 */
|
||||||
/** Sets the multi flag which eventually marks the emerging session as not
|
/* Sets the multi flag which eventually marks the emerging session as not being
|
||||||
being the last one and thus creating a BURN_DISC_APPENDABLE media.
|
the last one and thus creating a BURN_DISC_APPENDABLE media.
|
||||||
@param multi 1=media will be appendable, 0=media will be closed (default)
|
@param multi 1=media will be appendable, 0=media will be closed (default)
|
||||||
*/
|
*/
|
||||||
void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi);
|
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, 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)
|
|
||||||
*/
|
|
||||||
void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value);
|
|
||||||
|
|
||||||
|
|
||||||
/** Sets whether to read in raw mode or not
|
/** Sets whether to read in raw mode or not
|
||||||
@param opts The read opts to change
|
@param opts The read opts to change
|
||||||
@param raw_mode If non-zero, reading will be done in raw mode, so that everything in the data tracks on the
|
@param raw_mode If non-zero, reading will be done in raw mode, so that everything in the data tracks on the
|
||||||
@ -1350,9 +1106,7 @@ void burn_read_opts_transfer_damaged_blocks(struct burn_read_opts *opts,
|
|||||||
void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts,
|
void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts,
|
||||||
unsigned char hardware_error_retries);
|
unsigned char hardware_error_retries);
|
||||||
|
|
||||||
/** Gets the maximum write speed for a drive and eventually loaded media.
|
/** Gets the maximum write speed for a drive
|
||||||
The return value might change by the media type of already loaded media,
|
|
||||||
again by call burn_drive_grab() and again by call burn_disc_read_atip().
|
|
||||||
@param d Drive to query
|
@param d Drive to query
|
||||||
@return Maximum write speed in K/s
|
@return Maximum write speed in K/s
|
||||||
*/
|
*/
|
||||||
@ -1360,9 +1114,8 @@ int burn_drive_get_write_speed(struct burn_drive *d);
|
|||||||
|
|
||||||
|
|
||||||
/* ts A61021 */
|
/* ts A61021 */
|
||||||
/** Gets the minimum write speed for a drive and eventually loaded media.
|
/** Gets the minimum write speed for a drive. This might differ from
|
||||||
The return value might change by the media type of already loaded media,
|
burn_drive_get_write_speed() only after burn_disc_read_atip()
|
||||||
again by call burn_drive_grab() and again by call burn_disc_read_atip().
|
|
||||||
@param d Drive to query
|
@param d Drive to query
|
||||||
@return Minimum write speed in K/s
|
@return Minimum write speed in K/s
|
||||||
*/
|
*/
|
||||||
@ -1375,130 +1128,6 @@ int burn_drive_get_min_write_speed(struct burn_drive *d);
|
|||||||
*/
|
*/
|
||||||
int burn_drive_get_read_speed(struct burn_drive *d);
|
int burn_drive_get_read_speed(struct burn_drive *d);
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
/** Obtain a copy of the current speed descriptor list. The drive's list gets
|
|
||||||
updated on various occasions such as burn_drive_grab() but the copy
|
|
||||||
obtained here stays untouched. It has to be disposed via
|
|
||||||
burn_drive_free_speedlist() when it is not longer needed. Speeds
|
|
||||||
may appear several times in the list. The list content depends much on
|
|
||||||
drive and media type. It seems that .source == 1 applies mostly to CD media
|
|
||||||
whereas .source == 2 applies to any media.
|
|
||||||
@param d Drive to query
|
|
||||||
@param speed_list The copy. If empty, *speed_list gets returned as NULL.
|
|
||||||
@return 1=success , 0=list empty , <0 severe error
|
|
||||||
*/
|
|
||||||
int burn_drive_get_speedlist(struct burn_drive *d,
|
|
||||||
struct burn_speed_descriptor **speed_list);
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
/** Dispose a speed descriptor list copy which was obtained by
|
|
||||||
burn_drive_get_speedlist().
|
|
||||||
@param speed_list The list copy. *speed_list gets set to NULL.
|
|
||||||
@return 1=list disposed , 0= *speedlist was already NULL
|
|
||||||
*/
|
|
||||||
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
|
/** Gets a copy of the toc_entry structure associated with a track
|
||||||
@param t Track to get the entry from
|
@param t Track to get the entry from
|
||||||
@param entry Struct for the library to fill out
|
@param entry Struct for the library to fill out
|
||||||
@ -1576,10 +1205,9 @@ int burn_msgs_set_severities(char *queue_severity,
|
|||||||
/** Obtain the oldest pending libburn message from the queue which has at
|
/** Obtain the oldest pending libburn message from the queue which has at
|
||||||
least the given minimum_severity. This message and any older message of
|
least the given minimum_severity. This message and any older message of
|
||||||
lower severity will get discarded from the queue and is then lost forever.
|
lower severity will get discarded from the queue and is then lost forever.
|
||||||
@param minimum_severity may be one of "NEVER", "FATAL", "SORRY",
|
Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
|
||||||
"WARNING", "HINT", "NOTE", "UPDATE", "DEBUG", "ALL".
|
"NOTE", "UPDATE", "DEBUG", "ALL". To call with minimum_severity "NEVER"
|
||||||
To call with minimum_severity "NEVER" will discard the
|
will discard the whole queue.
|
||||||
whole queue.
|
|
||||||
@param error_code Will become a unique error code as liste in
|
@param error_code Will become a unique error code as liste in
|
||||||
libburn/libdax_msgs.h
|
libburn/libdax_msgs.h
|
||||||
@param msg_text Must provide at least BURN_MSGS_MESSAGE_LEN bytes.
|
@param msg_text Must provide at least BURN_MSGS_MESSAGE_LEN bytes.
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
|
|
||||||
/* libdax_msgs
|
/* libdax_msgs
|
||||||
Message handling facility of libdax.
|
Message handling facility of libdax.
|
||||||
Copyright (C) 2006-2007 Thomas Schmitt <scdbackup@gmx.net>,
|
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
|
||||||
provided under GPL
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -335,32 +334,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x0002011a (NOTE,HIGH) = Padding up track to minimum size
|
0x0002011a (NOTE,HIGH) = Padding up track to minimum size
|
||||||
0x0002011b (FATAL,HIGH) = Attempt to read track info from ungrabbed drive
|
0x0002011b (FATAL,HIGH) = Attempt to read track info from ungrabbed drive
|
||||||
0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive
|
0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive
|
||||||
0x0002011d (FATAL,HIGH) = SCSI error on write
|
0x0002011d (FATAL,HIGH) = SCSI error condition on write
|
||||||
0x0002011e (SORRY,HIGH) = Unsuitable media detected
|
|
||||||
0x0002011f (SORRY,HIGH) = Burning is restricted to a single track
|
|
||||||
0x00020120 (NOTE,HIGH) = FORMAT UNIT ignored
|
|
||||||
0x00020121 (FATAL,HIGH) = Write preparation setup failed
|
|
||||||
0x00020122 (FATAL,HIGH) = SCSI error on format_unit
|
|
||||||
0x00020123 (SORRY,HIGH) = DVD Media are unsuitable for desired track type
|
|
||||||
0x00020124 (SORRY,HIGH) = SCSI error on set_streaming
|
|
||||||
0x00020125 (SORRY,HIGH) = Write start address not supported
|
|
||||||
0x00020126 (SORRY,HIGH) = Write start address not properly aligned
|
|
||||||
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:
|
libdax_audioxtr:
|
||||||
0x00020200 (SORRY,HIGH) = Cannot open audio source file
|
0x00020200 (SORRY,HIGH) = Cannot open audio source file
|
||||||
|
1506
libburn/mmc.c
1506
libburn/mmc.c
File diff suppressed because it is too large
Load Diff
@ -51,22 +51,4 @@ int mmc_read_buffer_capacity(struct burn_drive *d);
|
|||||||
*/
|
*/
|
||||||
int mmc_setup_drive(struct burn_drive *d);
|
int mmc_setup_drive(struct burn_drive *d);
|
||||||
|
|
||||||
/* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format()
|
|
||||||
and mmc5r03c.pdf, 6.5 FORMAT UNIT */
|
|
||||||
int mmc_format_unit(struct burn_drive *d, off_t size, int flag);
|
|
||||||
|
|
||||||
/* ts A61225 : obtain write speed descriptors via ACh GET PERFORMANCE */
|
|
||||||
int mmc_get_write_performance(struct burn_drive *d);
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61229 : outsourced from spc_select_write_params() */
|
|
||||||
/* Note: Page data is not zeroed here to allow preset defaults. Thus
|
|
||||||
memset(pd, 0, 2 + d->mdata->write_page_length);
|
|
||||||
is the eventual duty of the caller.
|
|
||||||
*/
|
|
||||||
int mmc_compose_mode_page_5(struct burn_drive *d,
|
|
||||||
const struct burn_write_opts *o,
|
|
||||||
unsigned char *pd);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*__MMC*/
|
#endif /*__MMC*/
|
||||||
|
@ -21,10 +21,6 @@ struct burn_source *burn_null_source_new(void)
|
|||||||
src->read_sub = NULL;
|
src->read_sub = NULL;
|
||||||
|
|
||||||
src->get_size = 0;
|
src->get_size = 0;
|
||||||
|
|
||||||
/* ts A70126 */
|
|
||||||
src->set_size = NULL;
|
|
||||||
|
|
||||||
src->free_data = NULL;
|
src->free_data = NULL;
|
||||||
src->data = NULL;
|
src->data = NULL;
|
||||||
return src;
|
return src;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "libburn.h"
|
#include "libburn.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "drive.h"
|
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
|
|
||||||
/* ts A61007 */
|
/* ts A61007 */
|
||||||
@ -33,9 +32,6 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
|
|||||||
opts->simulate = 0;
|
opts->simulate = 0;
|
||||||
opts->underrun_proof = drive->mdata->underrun_proof;
|
opts->underrun_proof = drive->mdata->underrun_proof;
|
||||||
opts->perform_opc = 1;
|
opts->perform_opc = 1;
|
||||||
opts->obs = -1;
|
|
||||||
opts->obs_pad = 0;
|
|
||||||
opts->start_byte = -1;
|
|
||||||
opts->has_mediacatalog = 0;
|
opts->has_mediacatalog = 0;
|
||||||
opts->format = BURN_CDROM;
|
opts->format = BURN_CDROM;
|
||||||
opts->multi = 0;
|
opts->multi = 0;
|
||||||
@ -156,7 +152,6 @@ void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts,
|
|||||||
memcpy(opts->mediacatalog, &mediacatalog, 13);
|
memcpy(opts->mediacatalog, &mediacatalog, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61106 */
|
/* ts A61106 */
|
||||||
void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
|
void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
|
||||||
{
|
{
|
||||||
@ -164,102 +159,6 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61222 */
|
|
||||||
void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value)
|
|
||||||
{
|
|
||||||
opts->start_byte = 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)
|
void burn_read_opts_set_raw(struct burn_read_opts *opts, int raw)
|
||||||
{
|
{
|
||||||
|
@ -32,15 +32,6 @@ struct burn_write_opts
|
|||||||
/** Perform calibration of the drive's laser before beginning the
|
/** Perform calibration of the drive's laser before beginning the
|
||||||
write. */
|
write. */
|
||||||
unsigned int perform_opc:1;
|
unsigned int perform_opc:1;
|
||||||
|
|
||||||
/* ts A61219 : Output block size to trigger buffer flush if hit.
|
|
||||||
-1 with CD, 32 kB with DVD */
|
|
||||||
int obs;
|
|
||||||
int obs_pad; /* 1=pad up last block to obs */
|
|
||||||
|
|
||||||
/* ts A61222 : Start address for media which allow a choice */
|
|
||||||
off_t start_byte;
|
|
||||||
|
|
||||||
/** A disc can have a media catalog number */
|
/** A disc can have a media catalog number */
|
||||||
int has_mediacatalog;
|
int has_mediacatalog;
|
||||||
unsigned char mediacatalog[13];
|
unsigned char mediacatalog[13];
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
|
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
|
/** List of all signals which shall be caught by signal handlers and trigger
|
||||||
a graceful abort of libburn. (See man 7 signal.)
|
a graceful abort of libburn. (See man 7 signal.)
|
||||||
*/
|
*/
|
||||||
@ -33,15 +37,14 @@
|
|||||||
|
|
||||||
/** To list all signals which shall surely not be caught */
|
/** To list all signals which shall surely not be caught */
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
|
SIGKILL, SIGCHLD, SIGSTOP, SIGURG
|
||||||
|
|
||||||
/* The number of above list items */
|
/* The number of above list items */
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT 5
|
#define BURN_OS_NON_SIGNAL_COUNT 4
|
||||||
|
|
||||||
|
|
||||||
/* The maximum size for a (SCSI) i/o transaction */
|
/* The maximum size for a (SCSI) i/o transaction */
|
||||||
/* Important : MUST be at least 32768 ! */
|
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536/2
|
||||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
|
|
||||||
|
|
||||||
|
|
||||||
/** To hold all state information of BSD device enumeration
|
/** To hold all state information of BSD device enumeration
|
||||||
@ -49,8 +52,13 @@ SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
|
|||||||
can work in BSD and sg_enumerate() can use it.
|
can work in BSD and sg_enumerate() can use it.
|
||||||
*/
|
*/
|
||||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
||||||
struct burn_drive_enumeration_state; \
|
struct burn_drive_enumeration_state { \
|
||||||
typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
|
union ccb ccb; \
|
||||||
|
int bufsize, fd; \
|
||||||
|
unsigned int i; \
|
||||||
|
int skip_device; \
|
||||||
|
}; \
|
||||||
|
typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;
|
||||||
|
|
||||||
|
|
||||||
/* The list of operating system dependent elements in struct burn_drive.
|
/* The list of operating system dependent elements in struct burn_drive.
|
||||||
@ -59,3 +67,6 @@ typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
|
|||||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
||||||
struct cam_device* cam;
|
struct cam_device* cam;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ! BURN_OS_H_INCLUDED */
|
||||||
|
|
||||||
|
@ -34,14 +34,13 @@
|
|||||||
|
|
||||||
/** To list all signals which shall surely not be caught */
|
/** To list all signals which shall surely not be caught */
|
||||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
||||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
|
SIGKILL, SIGCHLD, SIGSTOP, SIGURG
|
||||||
|
|
||||||
/* The number of above list items */
|
/* The number of above list items */
|
||||||
#define BURN_OS_NON_SIGNAL_COUNT 5
|
#define BURN_OS_NON_SIGNAL_COUNT 4
|
||||||
|
|
||||||
|
|
||||||
/* The maximum size for a (SCSI) i/o transaction */
|
/* The maximum size for a (SCSI) i/o transaction */
|
||||||
/* Important : MUST be at least 32768 ! */
|
|
||||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
||||||
|
|
||||||
|
|
||||||
|
@ -217,8 +217,7 @@ static unsigned char *get_sector(struct burn_write_opts *opts,
|
|||||||
return NULL;
|
return NULL;
|
||||||
seclen += burn_subcode_length(outmode);
|
seclen += burn_subcode_length(outmode);
|
||||||
|
|
||||||
/* ts A61219 : opts->obs is eventually a 32k trigger for DVD */
|
if (out->bytes + (seclen) >= BUFFER_SIZE) {
|
||||||
if (out->bytes + (seclen) > BUFFER_SIZE || out->bytes == opts->obs) {
|
|
||||||
int err;
|
int err;
|
||||||
err = d->write(d, d->nwa, out);
|
err = d->write(d, d->nwa, out);
|
||||||
if (err == BE_CANCELLED)
|
if (err == BE_CANCELLED)
|
||||||
@ -643,10 +642,7 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ts A61219 : allow track without .entry */
|
if (!t->source->read_sub)
|
||||||
if (t->entry == NULL)
|
|
||||||
;
|
|
||||||
else if (!t->source->read_sub)
|
|
||||||
subcode_user(o, subs, t->entry->point,
|
subcode_user(o, subs, t->entry->point,
|
||||||
t->entry->control, 1, &t->isrc, psub);
|
t->entry->control, 1, &t->isrc, psub);
|
||||||
else if (!t->source->read_sub(t->source, subs, 96))
|
else if (!t->source->read_sub(t->source, subs, 96))
|
||||||
|
@ -1,5 +1,19 @@
|
|||||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
/* -*- 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 <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -31,13 +45,6 @@
|
|||||||
#include "libdax_msgs.h"
|
#include "libdax_msgs.h"
|
||||||
extern struct libdax_msgs *libdax_messenger;
|
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,
|
static void enumerate_common(char *fname, int bus_no, int host_no,
|
||||||
int channel_no, int target_no, int lun_no);
|
int channel_no, int target_no, int lun_no);
|
||||||
|
|
||||||
@ -50,20 +57,33 @@ int burn_drive_is_banned(char *device_address);
|
|||||||
int mmc_function_spy(char * text);
|
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
|
/* ts A61021 : Moved most code from scsi_enumerate_drives under
|
||||||
sg_give_next_adr() */
|
sg_give_next_adr() */
|
||||||
/* Some helper functions for scsi_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;
|
idx->skip_device = 0;
|
||||||
|
|
||||||
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
|
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
|
||||||
@ -78,13 +98,12 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
|
|||||||
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
|
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
|
||||||
|
|
||||||
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
|
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
|
||||||
bufsize = sizeof(struct dev_match_result) * 100;
|
idx->bufsize = sizeof(struct dev_match_result) * 100;
|
||||||
idx->ccb.cdm.match_buf_len = bufsize;
|
idx->ccb.cdm.match_buf_len = idx->bufsize;
|
||||||
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
|
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(idx->bufsize);
|
||||||
if (idx->ccb.cdm.matches == NULL) {
|
if (idx->ccb.cdm.matches == NULL) {
|
||||||
warnx("can't malloc memory for matches");
|
warnx("can't malloc memory for matches");
|
||||||
close(idx->fd);
|
close(idx->fd);
|
||||||
free(idx);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
idx->ccb.cdm.num_matches = 0;
|
idx->ccb.cdm.num_matches = 0;
|
||||||
@ -97,28 +116,12 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
|
|||||||
idx->ccb.cdm.num_patterns = 0;
|
idx->ccb.cdm.num_patterns = 0;
|
||||||
idx->ccb.cdm.pattern_buf_len = 0;
|
idx->ccb.cdm.pattern_buf_len = 0;
|
||||||
|
|
||||||
*idx_ = idx;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sg_destroy_enumerator(burn_drive_enumerator_t *idx_)
|
|
||||||
|
static int sg_next_enumeration_buffer(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
|
* We do the ioctl multiple times if necessary, in case there are
|
||||||
* more than 100 nodes in the EDT.
|
* more than 100 nodes in the EDT.
|
||||||
@ -149,40 +152,44 @@ static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
|
|||||||
@return 1 = reply is a valid address , 0 = no further address available
|
@return 1 = reply is a valid address , 0 = no further address available
|
||||||
-1 = severe error (e.g. adr_size too small)
|
-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)
|
char adr[], int adr_size, int initialize)
|
||||||
{
|
{
|
||||||
struct burn_drive_enumeration_state *idx;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (initialize == 1) {
|
if (initialize == 1) {
|
||||||
ret = sg_init_enumerator(idx_);
|
ret = sg_init_enumerator(idx);
|
||||||
if (ret<=0)
|
if (ret<=0)
|
||||||
return ret;
|
return ret;
|
||||||
} else if (initialize == -1) {
|
} else if (initialize == -1) {
|
||||||
sg_destroy_enumerator(idx_);
|
if(idx->fd != -1)
|
||||||
|
close(idx->fd);
|
||||||
|
idx->fd = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = *idx_;
|
|
||||||
|
|
||||||
do {
|
try_item:; /* This spaghetti loop keeps the number of tabs small */
|
||||||
if (idx->i >= idx->ccb.cdm.num_matches) {
|
|
||||||
ret = sg_next_enumeration_buffer(idx_);
|
/* Loop content from old scsi_enumerate_drives() */
|
||||||
|
|
||||||
|
while (idx->i >= idx->ccb.cdm.num_matches) {
|
||||||
|
ret = sg_next_enumeration_buffer(idx);
|
||||||
if (ret<=0)
|
if (ret<=0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
|
||||||
|
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
|
||||||
|
return 0;
|
||||||
idx->i = 0;
|
idx->i = 0;
|
||||||
} else
|
}
|
||||||
(idx->i)++;
|
|
||||||
|
|
||||||
while (idx->i < idx->ccb.cdm.num_matches) {
|
|
||||||
switch (idx->ccb.cdm.matches[idx->i].type) {
|
switch (idx->ccb.cdm.matches[idx->i].type) {
|
||||||
case DEV_MATCH_BUS:
|
case DEV_MATCH_BUS:
|
||||||
break;
|
break;
|
||||||
case DEV_MATCH_DEVICE: {
|
case DEV_MATCH_DEVICE: {
|
||||||
struct device_match_result* result;
|
struct device_match_result* result;
|
||||||
|
|
||||||
result = &(idx->ccb.cdm.matches[idx->i].result.device_result);
|
result = &(idx->ccb.cdm.matches[i].result.device_result);
|
||||||
if (result->flags & DEV_RESULT_UNCONFIGURED)
|
if (result->flags & DEV_RESULT_UNCONFIGURED)
|
||||||
idx->skip_device = 1;
|
idx->skip_device = 1;
|
||||||
else
|
else
|
||||||
@ -191,15 +198,17 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx_,
|
|||||||
}
|
}
|
||||||
case DEV_MATCH_PERIPH: {
|
case DEV_MATCH_PERIPH: {
|
||||||
struct periph_match_result* result;
|
struct periph_match_result* result;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
|
result = &(idx->ccb.cdm.matches[i].result.periph_result);
|
||||||
if (idx->skip_device ||
|
if (idx->skip_device ||
|
||||||
strcmp(result->periph_name, "pass") == 0)
|
strcmp(result->periph_name, "pass") == 0)
|
||||||
break;
|
break;
|
||||||
ret = snprintf(adr, adr_size, "/dev/%s%d",
|
snprintf(buf, sizeof (buf), "/dev/%s%d",
|
||||||
result->periph_name, result->unit_number);
|
result->periph_name, result->unit_number);
|
||||||
if(ret >= adr_size)
|
if(adr_size <= strlen(buf)
|
||||||
return -1;
|
return -1;
|
||||||
|
strcpy(adr, buf);
|
||||||
|
|
||||||
/* Found next enumerable address */
|
/* Found next enumerable address */
|
||||||
return 1;
|
return 1;
|
||||||
@ -209,34 +218,29 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx_,
|
|||||||
/* printf(stderr, "unknown match type\n"); */
|
/* printf(stderr, "unknown match type\n"); */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
(idx->i)++;
|
|
||||||
}
|
|
||||||
} while ((idx->ccb.ccb_h.status == CAM_REQ_CMP)
|
|
||||||
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE));
|
|
||||||
|
|
||||||
return 0;
|
(idx->i)++;
|
||||||
|
goto try_item; /* Regular function exit is return 1 above */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sg_is_enumerable_adr(char* adr)
|
int sg_is_enumerable_adr(char* adr)
|
||||||
{
|
{
|
||||||
burn_drive_enumerator_t idx;
|
burn_drive_enumerator_t idx;
|
||||||
int ret;
|
int initialize = 1;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
ret = sg_init_enumerator(&idx);
|
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
|
||||||
while(1) {
|
while(1) {
|
||||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
|
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
||||||
|
initialize = 0;
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
if (strcmp(adr, buf) == 0) {
|
if (strcmp(adr, buf) == 0) {
|
||||||
sg_destroy_enumerator(&idx);
|
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sg_destroy_enumerator(&idx);
|
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,32 +252,32 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
|||||||
int *target_no, int *lun_no)
|
int *target_no, int *lun_no)
|
||||||
{
|
{
|
||||||
burn_drive_enumerator_t idx;
|
burn_drive_enumerator_t idx;
|
||||||
int ret;
|
int initialize = 1;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
struct periph_match_result* result;
|
struct periph_match_result* result;
|
||||||
|
|
||||||
ret = sg_init_enumerator(&idx);
|
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
|
||||||
while(1) {
|
while(1) {
|
||||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
|
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
||||||
|
initialize = 0;
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
if (strcmp(path, buf) == 0) {
|
if (strcmp(adr, buf) != 0)
|
||||||
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
|
continue;
|
||||||
|
result = &(idx->ccb.cdm.matches[i].result.periph_result);
|
||||||
*bus_no = result->path_id;
|
*bus_no = result->path_id;
|
||||||
*host_no = result->path_id;
|
*host_no = result->path_id;
|
||||||
*channel_no = 0;
|
*channel_no = 0;
|
||||||
*target_no = result->target_id;
|
*target_no = result->target_id
|
||||||
*lun_no = result->target_lun;
|
*lun_no = result->target_lun;
|
||||||
sg_destroy_enumerator(&idx);
|
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||||
sg_destroy_enumerator(&idx);
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* ! Scsi_freebsd_old_scsi_enumeratE */
|
||||||
|
|
||||||
|
|
||||||
int sg_close_drive(struct burn_drive * d)
|
int sg_close_drive(struct burn_drive * d)
|
||||||
{
|
{
|
||||||
@ -291,28 +295,125 @@ int sg_drive_is_open(struct burn_drive * d)
|
|||||||
|
|
||||||
int scsi_enumerate_drives(void)
|
int scsi_enumerate_drives(void)
|
||||||
{
|
{
|
||||||
burn_drive_enumerator_t idx;
|
|
||||||
int ret;
|
|
||||||
char buf[64];
|
|
||||||
struct periph_match_result* result;
|
|
||||||
|
|
||||||
ret = sg_init_enumerator(&idx);
|
#ifdef Scsi_freebsd_old_scsi_enumeratE
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
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;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
|
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
||||||
|
initialize = 0;
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
if (burn_drive_is_banned(buf))
|
if (burn_drive_is_banned(buf))
|
||||||
continue;
|
continue;
|
||||||
result = &idx->ccb.cdm.matches[idx->i].result.periph_result;
|
enumerate_common(buf, idx.result->path_id, idx.result->path_id,
|
||||||
enumerate_common(buf, result->path_id, result->path_id,
|
0, idx.result->target_id,
|
||||||
0, result->target_id,
|
idx.result->target_lun);
|
||||||
result->target_lun);
|
|
||||||
}
|
}
|
||||||
sg_destroy_enumerator(&idx);
|
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||||
|
|
||||||
|
#endif /* ! Scsi_freebsd_old_scsi_enumeratE */
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -450,10 +551,7 @@ int sg_grab(struct burn_drive *d)
|
|||||||
|
|
||||||
mmc_function_spy("sg_grab");
|
mmc_function_spy("sg_grab");
|
||||||
|
|
||||||
if (burn_drive_is_open(d)) {
|
assert(d->cam == NULL);
|
||||||
d->released = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cam = cam_open_device(d->devname, O_RDWR);
|
cam = cam_open_device(d->devname, O_RDWR);
|
||||||
if (cam == NULL) {
|
if (cam == NULL) {
|
||||||
@ -493,7 +591,6 @@ int sg_release(struct burn_drive *d)
|
|||||||
mmc_function_spy("sg_release ----------- closing.");
|
mmc_function_spy("sg_release ----------- closing.");
|
||||||
|
|
||||||
sg_close_drive(d);
|
sg_close_drive(d);
|
||||||
d->released = 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,70 +74,6 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
|
|||||||
#include <scsi/sg.h>
|
#include <scsi/sg.h>
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
|
|
||||||
/* ts A61211 : to recognize CD devices on /dev/sr* */
|
|
||||||
#include <linux/cdrom.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61211 : preparing for exploration of recent Linux ATA adventures */
|
|
||||||
/** PORTING : Device file families for bus scanning and drive access.
|
|
||||||
Both device families must support the following ioctls:
|
|
||||||
SG_IO,
|
|
||||||
SG_GET_SCSI_ID
|
|
||||||
SCSI_IOCTL_GET_BUS_NUMBER
|
|
||||||
SCSI_IOCTL_GET_IDLUN
|
|
||||||
as well as mutual exclusively locking with open(O_EXCL).
|
|
||||||
If a device family is left empty, then it will not be used.
|
|
||||||
|
|
||||||
To avoid misunderstandings: both families are used via identical
|
|
||||||
transport methods as soon as a device file is accepted as CD drive
|
|
||||||
by the family specific function <family>_enumerate().
|
|
||||||
One difference remains throughout usage: Host,Channel,Id,Lun and Bus
|
|
||||||
address parameters of ATA devices are considered invalid.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Set this to 1 in order to get on stderr messages from sg_enumerate() */
|
|
||||||
static int linux_sg_enumerate_debug = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* The device file family to use for (emulated) generic SCSI transport.
|
|
||||||
This must be a printf formatter with one single placeholder for int
|
|
||||||
in the range of 0 to 31 . The resulting addresses must provide SCSI
|
|
||||||
address parameters Host, Channel, Id, Lun and also Bus.
|
|
||||||
E.g.: "/dev/sg%d"
|
|
||||||
*/
|
|
||||||
/* NEW INFO: If hard disks at /dev/sr allow ioctl(CDROM_DRIVE_STATUS), they
|
|
||||||
are in danger.
|
|
||||||
If you want it less dangerous:
|
|
||||||
#undef CDROM_DRIVE_STATUS
|
|
||||||
but then you might need linux_sg_accept_any_type = 1 which
|
|
||||||
is _more dangerous_.
|
|
||||||
*/
|
|
||||||
/* !!! DO NOT SET TO sr%d UNLESS YOU PROTECTED ALL INDISPENSIBLE DEVICES
|
|
||||||
by chmod -rw . A test wether non-CD devices are properly excluded would
|
|
||||||
be well needed though. Heroic disks, scanners, etc. wanted !!! */
|
|
||||||
static char linux_sg_device_family[80] = {"/dev/sg%d"};
|
|
||||||
|
|
||||||
|
|
||||||
/* Set this to 1 in order to accept any TYPE_* (see scsi/scsi.h) */
|
|
||||||
/* NEW INFO: Try with 0 first. There is hope via CDROM_DRIVE_STATUS. */
|
|
||||||
/* !!! DO NOT SET TO 1 UNLESS YOU PROTECTED ALL INDISPENSIBLE DEVICES
|
|
||||||
chmod -rw !!! */
|
|
||||||
static int linux_sg_accept_any_type = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* The device file family to use for SCSI transport over ATA.
|
|
||||||
This must be a printf formatter with one single placeholder for a
|
|
||||||
_single_ char in the range of 'a' to 'z'. This placeholder _must_ be
|
|
||||||
at the end of the formatter string.
|
|
||||||
E.g. "/dev/hd%c"
|
|
||||||
*/
|
|
||||||
static char linux_ata_device_family[80] = {"/dev/hd%c"};
|
|
||||||
|
|
||||||
/* Set this to 1 in order to get on stderr messages from ata_enumerate()
|
|
||||||
*/
|
|
||||||
static int linux_ata_enumerate_verbous = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** PORTING : ------ libburn portable headers and definitions ----- */
|
/** PORTING : ------ libburn portable headers and definitions ----- */
|
||||||
|
|
||||||
@ -349,11 +285,7 @@ static int sg_open_scsi_siblings(char *path, int driveno,
|
|||||||
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
|
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
|
||||||
char msg[161], fname[81];
|
char msg[161], fname[81];
|
||||||
|
|
||||||
static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/st%d",
|
static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/st%d", ""};
|
||||||
"/dev/sg%d", ""};
|
|
||||||
|
|
||||||
if (linux_sg_device_family[0] == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if(host_no < 0 || id_no < 0 || channel_no < 0 || lun_no < 0)
|
if(host_no < 0 || id_no < 0 || channel_no < 0 || lun_no < 0)
|
||||||
return(2);
|
return(2);
|
||||||
@ -361,8 +293,6 @@ static int sg_open_scsi_siblings(char *path, int driveno,
|
|||||||
sg_release_siblings(sibling_fds, sibling_count);
|
sg_release_siblings(sibling_fds, sibling_count);
|
||||||
|
|
||||||
for (tld = 0; tldev[tld][0] != 0; tld++) {
|
for (tld = 0; tldev[tld][0] != 0; tld++) {
|
||||||
if (strcmp(tldev[tld], linux_sg_device_family)==0)
|
|
||||||
continue;
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
sprintf(fname, tldev[tld], i);
|
sprintf(fname, tldev[tld], i);
|
||||||
ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
|
ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
|
||||||
@ -397,7 +327,7 @@ static int sg_open_scsi_siblings(char *path, int driveno,
|
|||||||
(*sibling_count)++;
|
(*sibling_count)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return(1);
|
||||||
failed:;
|
failed:;
|
||||||
sg_release_siblings(sibling_fds, sibling_count);
|
sg_release_siblings(sibling_fds, sibling_count);
|
||||||
return 0;
|
return 0;
|
||||||
@ -412,39 +342,20 @@ static void ata_enumerate(void)
|
|||||||
int i, fd;
|
int i, fd;
|
||||||
char fname[10];
|
char fname[10];
|
||||||
|
|
||||||
if (linux_ata_enumerate_verbous)
|
|
||||||
fprintf(stderr, "libburn_debug: linux_ata_device_family = %s\n",
|
|
||||||
linux_ata_device_family);
|
|
||||||
|
|
||||||
if (linux_ata_device_family[0] == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < 26; i++) {
|
for (i = 0; i < 26; i++) {
|
||||||
sprintf(fname, linux_ata_device_family, 'a' + i);
|
sprintf(fname, "/dev/hd%c", 'a' + i);
|
||||||
if (linux_ata_enumerate_verbous)
|
|
||||||
fprintf(stderr, "libburn_debug: %s : ", fname);
|
|
||||||
|
|
||||||
/* ts A51221 */
|
/* ts A51221 */
|
||||||
if (burn_drive_is_banned(fname)) {
|
if (burn_drive_is_banned(fname))
|
||||||
if (linux_ata_enumerate_verbous)
|
|
||||||
fprintf(stderr, "not in whitelist\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
fd = sg_open_drive_fd(fname, 1);
|
fd = sg_open_drive_fd(fname, 1);
|
||||||
if (fd == -1) {
|
if (fd == -1)
|
||||||
if (linux_ata_enumerate_verbous)
|
|
||||||
fprintf(stderr,"open failed, errno=%d '%s'\n",
|
|
||||||
errno, strerror(errno));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/* found a drive */
|
/* found a drive */
|
||||||
ioctl(fd, HDIO_GET_IDENTITY, &tm);
|
ioctl(fd, HDIO_GET_IDENTITY, &tm);
|
||||||
|
|
||||||
/* not atapi */
|
/* not atapi */
|
||||||
if (!(tm.config & 0x8000) || (tm.config & 0x4000)) {
|
if (!(tm.config & 0x8000) || (tm.config & 0x4000)) {
|
||||||
if (linux_ata_enumerate_verbous)
|
|
||||||
fprintf(stderr, "not marked as ATAPI\n");
|
|
||||||
sg_close_drive_fd(fname, -1, &fd, 0);
|
sg_close_drive_fd(fname, -1, &fd, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -452,22 +363,11 @@ static void ata_enumerate(void)
|
|||||||
/* if SG_IO fails on an atapi device, we should stop trying to
|
/* if SG_IO fails on an atapi device, we should stop trying to
|
||||||
use hd* devices */
|
use hd* devices */
|
||||||
if (sgio_test(fd) == -1) {
|
if (sgio_test(fd) == -1) {
|
||||||
if (linux_ata_enumerate_verbous)
|
|
||||||
fprintf(stderr,
|
|
||||||
"FATAL: sgio_test() failed: errno=%d '%s'\n",
|
|
||||||
errno, strerror(errno));
|
|
||||||
sg_close_drive_fd(fname, -1, &fd, 0);
|
sg_close_drive_fd(fname, -1, &fd, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0) {
|
if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0)
|
||||||
if (linux_ata_enumerate_verbous)
|
|
||||||
fprintf(stderr,
|
|
||||||
"cannot close properly, errno=%d '%s'\n",
|
|
||||||
errno, strerror(errno));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (linux_ata_enumerate_verbous)
|
|
||||||
fprintf(stderr, "accepting as drive without SCSI address\n");
|
|
||||||
enumerate_common(fname, -1, -1, -1, -1, -1);
|
enumerate_common(fname, -1, -1, -1, -1, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -478,66 +378,21 @@ static void sg_enumerate(void)
|
|||||||
{
|
{
|
||||||
struct sg_scsi_id sid;
|
struct sg_scsi_id sid;
|
||||||
int i, fd, sibling_fds[LIBBURN_SG_MAX_SIBLINGS], sibling_count= 0, ret;
|
int i, fd, sibling_fds[LIBBURN_SG_MAX_SIBLINGS], sibling_count= 0, ret;
|
||||||
int sid_ret = 0;
|
int bus_no = -1;
|
||||||
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
|
|
||||||
char fname[10];
|
char fname[10];
|
||||||
|
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr, "libburn_debug: linux_sg_device_family = %s\n",
|
|
||||||
linux_sg_device_family);
|
|
||||||
|
|
||||||
if (linux_sg_device_family[0] == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
sprintf(fname, linux_sg_device_family, i);
|
sprintf(fname, "/dev/sg%d", i);
|
||||||
|
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr, "libburn_debug: %s : ", fname);
|
|
||||||
|
|
||||||
/* ts A51221 */
|
/* ts A51221 */
|
||||||
if (burn_drive_is_banned(fname)) {
|
if (burn_drive_is_banned(fname))
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr, "not in whitelist\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/* ts A60927 */
|
/* ts A60927 */
|
||||||
fd = sg_open_drive_fd(fname, 1);
|
fd = sg_open_drive_fd(fname, 1);
|
||||||
if (fd == -1) {
|
if (fd == -1)
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr, "open failed, errno=%d '%s'\n",
|
|
||||||
errno, strerror(errno));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/* found a drive */
|
/* found a drive */
|
||||||
sid_ret = ioctl(fd, SG_GET_SCSI_ID, &sid);
|
ioctl(fd, SG_GET_SCSI_ID, &sid);
|
||||||
if (sid_ret == -1) {
|
|
||||||
sid.scsi_id = -1; /* mark SCSI address as invalid */
|
|
||||||
if(linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr,
|
|
||||||
"ioctl(SG_GET_SCSI_ID) failed, errno=%d '%s' , ",
|
|
||||||
errno, strerror(errno));
|
|
||||||
|
|
||||||
#ifdef CDROM_DRIVE_STATUS
|
|
||||||
/* ts A61211 : not widening old acceptance range */
|
|
||||||
if (strcmp(linux_sg_device_family,"/dev/sg%d") != 0) {
|
|
||||||
/* http://developer.osdl.org/dev/robustmutexes/
|
|
||||||
src/fusyn.hg/Documentation/ioctl/cdrom.txt */
|
|
||||||
sid_ret = ioctl(fd, CDROM_DRIVE_STATUS, 0);
|
|
||||||
if(linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr,
|
|
||||||
"ioctl(CDROM_DRIVE_STATUS) = %d , ",
|
|
||||||
sid_ret);
|
|
||||||
if (sid_ret != -1 && sid_ret != CDS_NO_INFO)
|
|
||||||
sid.scsi_type = TYPE_ROM;
|
|
||||||
else
|
|
||||||
sid_ret = -1;
|
|
||||||
}
|
|
||||||
#endif /* CDROM_DRIVE_STATUS */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
|
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
|
||||||
/* Hearsay A61005 */
|
/* Hearsay A61005 */
|
||||||
@ -546,37 +401,10 @@ static void sg_enumerate(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sg_close_drive_fd(fname, -1, &fd,
|
if (sg_close_drive_fd(fname, -1, &fd,
|
||||||
sid.scsi_type == TYPE_ROM ) <= 0) {
|
sid.scsi_type == TYPE_ROM ) <= 0)
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr,
|
|
||||||
"cannot close properly, errno=%d '%s'\n",
|
|
||||||
errno, strerror(errno));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
if (sid.scsi_type != TYPE_ROM)
|
||||||
if ( (sid_ret == -1 || sid.scsi_type != TYPE_ROM)
|
|
||||||
&& !linux_sg_accept_any_type) {
|
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr, "sid.scsi_type = %d (!= TYPE_ROM)\n",
|
|
||||||
sid.scsi_type);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (sid_ret == -1 || sid.scsi_id < 0) {
|
|
||||||
/* ts A61211 : employ a more general ioctl */
|
|
||||||
ret = sg_obtain_scsi_adr(fname, &bus_no, &host_no,
|
|
||||||
&channel_no, &target_no, &lun_no);
|
|
||||||
if (ret>0) {
|
|
||||||
sid.host_no = host_no;
|
|
||||||
sid.channel = channel_no;
|
|
||||||
sid.scsi_id = target_no;
|
|
||||||
sid.lun = lun_no;
|
|
||||||
} else {
|
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr,
|
|
||||||
"sg_obtain_scsi_adr() failed\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ts A60927 : trying to do locking with growisofs */
|
/* ts A60927 : trying to do locking with growisofs */
|
||||||
if(burn_sg_open_o_excl>1) {
|
if(burn_sg_open_o_excl>1) {
|
||||||
@ -585,8 +413,6 @@ static void sg_enumerate(void)
|
|||||||
sid.host_no, sid.channel,
|
sid.host_no, sid.channel,
|
||||||
sid.scsi_id, sid.lun);
|
sid.scsi_id, sid.lun);
|
||||||
if (ret<=0) {
|
if (ret<=0) {
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr, "cannot lock siblings\n");
|
|
||||||
sg_handle_busy_device(fname, 0);
|
sg_handle_busy_device(fname, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -599,10 +425,6 @@ static void sg_enumerate(void)
|
|||||||
#else
|
#else
|
||||||
bus_no = sid.host_no;
|
bus_no = sid.host_no;
|
||||||
#endif
|
#endif
|
||||||
if (linux_sg_enumerate_debug)
|
|
||||||
fprintf(stderr, "accepting as SCSI %d,%d,%d,%d bus=%d\n",
|
|
||||||
sid.host_no, sid.channel, sid.scsi_id, sid.lun,
|
|
||||||
bus_no);
|
|
||||||
enumerate_common(fname, bus_no, sid.host_no, sid.channel,
|
enumerate_common(fname, bus_no, sid.host_no, sid.channel,
|
||||||
sid.scsi_id, sid.lun);
|
sid.scsi_id, sid.lun);
|
||||||
}
|
}
|
||||||
@ -691,18 +513,13 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
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)
|
char adr[], int adr_size, int initialize)
|
||||||
{
|
{
|
||||||
/* os-linux.h : typedef int burn_drive_enumerator_t; */
|
/* sg.h : typedef int burn_drive_enumerator_t; */
|
||||||
static int sg_limit = 32, ata_limit = 26;
|
static int sg_limit = 32, ata_limit = 26;
|
||||||
int baseno = 0;
|
int baseno = 0;
|
||||||
|
|
||||||
if (initialize == -1)
|
if (initialize == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (linux_sg_device_family[0] == 0)
|
|
||||||
sg_limit = 0;
|
|
||||||
if (linux_ata_device_family[0] == 0)
|
|
||||||
ata_limit = 0;
|
|
||||||
|
|
||||||
if (initialize == 1)
|
if (initialize == 1)
|
||||||
*idx = -1;
|
*idx = -1;
|
||||||
(*idx)++;
|
(*idx)++;
|
||||||
@ -710,7 +527,7 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx,
|
|||||||
goto next_ata;
|
goto next_ata;
|
||||||
if (adr_size < 10)
|
if (adr_size < 10)
|
||||||
return -1;
|
return -1;
|
||||||
sprintf(adr, linux_sg_device_family, *idx);
|
sprintf(adr, "/dev/sg%d", *idx);
|
||||||
return 1;
|
return 1;
|
||||||
next_ata:;
|
next_ata:;
|
||||||
baseno += sg_limit;
|
baseno += sg_limit;
|
||||||
@ -718,7 +535,7 @@ next_ata:;
|
|||||||
goto next_nothing;
|
goto next_nothing;
|
||||||
if (adr_size < 9)
|
if (adr_size < 9)
|
||||||
return -1;
|
return -1;
|
||||||
sprintf(adr, linux_ata_device_family, 'a' + (*idx - baseno));
|
sprintf(adr, "/dev/hd%c", 'a' + (*idx - baseno));
|
||||||
return 1;
|
return 1;
|
||||||
next_nothing:;
|
next_nothing:;
|
||||||
baseno += ata_limit;
|
baseno += ata_limit;
|
||||||
@ -1034,15 +851,14 @@ ex:;
|
|||||||
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
||||||
int *target_no, int *lun_no)
|
int *target_no, int *lun_no)
|
||||||
{
|
{
|
||||||
int fd, ret, l;
|
int fd, ret;
|
||||||
struct my_scsi_idlun {
|
struct my_scsi_idlun {
|
||||||
int x;
|
int x;
|
||||||
int host_unique_id;
|
int host_unique_id;
|
||||||
};
|
};
|
||||||
struct my_scsi_idlun idlun;
|
struct my_scsi_idlun idlun;
|
||||||
|
|
||||||
l = strlen(linux_ata_device_family) - 2;
|
if (strncmp(path, "/dev/hd", 7) == 0
|
||||||
if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0
|
|
||||||
&& path[7] >= 'a' && path[7] <= 'z' && path[8] == 0)
|
&& path[7] >= 'a' && path[7] <= 'z' && path[8] == 0)
|
||||||
return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */
|
return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */
|
||||||
|
|
||||||
|
127
libburn/spc.c
127
libburn/spc.c
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "libburn.h"
|
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
#include "spc.h"
|
#include "spc.h"
|
||||||
#include "mmc.h"
|
#include "mmc.h"
|
||||||
@ -133,13 +132,9 @@ void spc_sense_caps(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct scsi_mode_data *m;
|
struct scsi_mode_data *m;
|
||||||
int size, page_length, num_write_speeds = 0, i, speed, ret;
|
int size;
|
||||||
unsigned char *page;
|
unsigned char *page;
|
||||||
struct command c;
|
struct command c;
|
||||||
struct burn_speed_descriptor *sd;
|
|
||||||
|
|
||||||
/* ts A61225 : 1 = report about post-MMC-1 speed descriptors */
|
|
||||||
static int speed_debug = 0;
|
|
||||||
|
|
||||||
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||||
c.retry = 1;
|
c.retry = 1;
|
||||||
@ -155,17 +150,6 @@ void spc_sense_caps(struct burn_drive *d)
|
|||||||
m = d->mdata;
|
m = d->mdata;
|
||||||
page = c.page->data + 8;
|
page = c.page->data + 8;
|
||||||
|
|
||||||
/* ts A61225 :
|
|
||||||
Although MODE SENSE indeed belongs to SPC, the returned code page
|
|
||||||
2Ah is part of MMC-1 to MMC-3. In MMC-1 5.2.3.4. it has 22 bytes,
|
|
||||||
in MMC-3 6.3.11 there are at least 28 bytes plus a variable length
|
|
||||||
set of speed descriptors. In MMC-5 E.11 it is declared "legacy".
|
|
||||||
*/
|
|
||||||
page_length = page[1];
|
|
||||||
|
|
||||||
m->valid = 0;
|
|
||||||
burn_mdata_free_subs(m);
|
|
||||||
|
|
||||||
m->buffer_size = page[12] * 256 + page[13];
|
m->buffer_size = page[12] * 256 + page[13];
|
||||||
m->dvdram_read = page[2] & 32;
|
m->dvdram_read = page[2] & 32;
|
||||||
m->dvdram_write = page[3] & 32;
|
m->dvdram_write = page[3] & 32;
|
||||||
@ -178,82 +162,27 @@ void spc_sense_caps(struct burn_drive *d)
|
|||||||
m->cdr_read = page[2] & 1;
|
m->cdr_read = page[2] & 1;
|
||||||
m->cdr_write = page[3] & 1;
|
m->cdr_write = page[3] & 1;
|
||||||
|
|
||||||
m->c2_pointers = page[5] & 16;
|
|
||||||
m->underrun_proof = page[4] & 128;
|
|
||||||
|
|
||||||
/* ts A61021 : these fields are marked obsolete in MMC 3 */
|
/* ts A61021 : these fields are marked obsolete in MMC 3 */
|
||||||
m->max_read_speed = page[8] * 256 + page[9];
|
m->max_read_speed = page[8] * 256 + page[9];
|
||||||
m->cur_read_speed = page[14] * 256 + page[15];
|
m->cur_read_speed = page[14] * 256 + page[15];
|
||||||
|
|
||||||
|
/* in MMC-3 : see [30-31] and blocks beginning at [32] */
|
||||||
m->max_write_speed = page[18] * 256 + page[19];
|
m->max_write_speed = page[18] * 256 + page[19];
|
||||||
m->cur_write_speed = page[20] * 256 + page[21];
|
/* New field to be set by atip */
|
||||||
|
|
||||||
/* ts A61021 : New field to be set by atip (or following MMC-3 info) */
|
|
||||||
m->min_write_speed = m->max_write_speed;
|
m->min_write_speed = m->max_write_speed;
|
||||||
|
|
||||||
/* ts A61225 : for ACh GET PERFORMANCE, Type 03h */
|
/* in MMC-3 : [28-29] */
|
||||||
m->min_end_lba = 0x7fffffff;
|
m->cur_write_speed = page[20] * 256 + page[21];
|
||||||
m->max_end_lba = 0;
|
|
||||||
|
|
||||||
|
/* >>> ts A61021 : iterate over all speeds :
|
||||||
|
data[30-31]: number of speed performance descriptor blocks
|
||||||
|
data[32-35]: block 0 : [+2-3] speed in kbytes/sec
|
||||||
|
*/
|
||||||
|
|
||||||
|
m->c2_pointers = page[5] & 16;
|
||||||
m->valid = 1;
|
m->valid = 1;
|
||||||
|
m->underrun_proof = page[4] & 128;
|
||||||
mmc_get_configuration(d);
|
|
||||||
|
|
||||||
/* ts A61225 : end of MMC-1 , begin of MMC-3 */
|
|
||||||
if (page_length < 32) /* no write speed descriptors ? */
|
|
||||||
goto try_mmc_get_performance;
|
|
||||||
|
|
||||||
m->cur_write_speed = page[28] * 256 + page[29];
|
|
||||||
|
|
||||||
if (speed_debug)
|
|
||||||
fprintf(stderr, "LIBBURN_DEBUG: cur_write_speed = %d\n",
|
|
||||||
m->cur_write_speed);
|
|
||||||
|
|
||||||
num_write_speeds = page[30] * 256 + page[31];
|
|
||||||
m->max_write_speed = m->min_write_speed = m->cur_write_speed;
|
|
||||||
for (i = 0; i < num_write_speeds; i++) {
|
|
||||||
speed = page[32 + 4*i + 2] * 256 + page[32 + 4*i + 3];
|
|
||||||
|
|
||||||
if (speed_debug)
|
|
||||||
fprintf(stderr,
|
|
||||||
"LIBBURN_DEBUG: write speed #%d = %d kB/s (rc %d)\n",
|
|
||||||
i, speed, page[32 + 4*i +1] & 7);
|
|
||||||
|
|
||||||
/* ts A61226 */
|
|
||||||
ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
|
|
||||||
NULL, d->mdata->speed_descriptors, 0);
|
|
||||||
if (ret > 0) {
|
|
||||||
sd = d->mdata->speed_descriptors;
|
|
||||||
sd->source = 1;
|
|
||||||
if (d->current_profile > 0) {
|
|
||||||
sd->profile_loaded = d->current_profile;
|
|
||||||
strcpy(sd->profile_name,
|
|
||||||
d->current_profile_text);
|
|
||||||
}
|
}
|
||||||
sd->wrc = (( page[32 + 4*i +1] & 7 ) == 1 );
|
|
||||||
sd->write_speed = speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (speed > m->max_write_speed)
|
|
||||||
m->max_write_speed = speed;
|
|
||||||
if (speed < m->min_write_speed)
|
|
||||||
m->min_write_speed = speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (speed_debug)
|
|
||||||
fprintf(stderr,
|
|
||||||
"LIBBURN_DEBUG: 5Ah,2Ah min_write_speed = %d , max_write_speed = %d\n",
|
|
||||||
m->min_write_speed, m->max_write_speed);
|
|
||||||
|
|
||||||
try_mmc_get_performance:;
|
|
||||||
ret = mmc_get_write_performance(d);
|
|
||||||
|
|
||||||
if (ret > 0 && speed_debug)
|
|
||||||
fprintf(stderr,
|
|
||||||
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
|
|
||||||
m->min_write_speed, m->max_write_speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void spc_sense_error_params(struct burn_drive *d)
|
void spc_sense_error_params(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
@ -345,11 +274,6 @@ void spc_sense_write_params(struct burn_drive *d)
|
|||||||
mmc_read_disc_info(d);
|
mmc_read_disc_info(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61229 */
|
|
||||||
#define Libburn_mmc_compose_mode_page_5 1
|
|
||||||
|
|
||||||
|
|
||||||
/* remark ts A61104 :
|
/* remark ts A61104 :
|
||||||
Although command MODE SELECT is SPC, the content of the
|
Although command MODE SELECT is SPC, the content of the
|
||||||
Write Parameters Mode Page (05h) is MMC (Table 108 in MMC-1).
|
Write Parameters Mode Page (05h) is MMC (Table 108 in MMC-1).
|
||||||
@ -360,9 +284,7 @@ void spc_select_write_params(struct burn_drive *d,
|
|||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct command c;
|
struct command c;
|
||||||
#ifndef Libburn_mmc_compose_mode_page_5
|
|
||||||
int bufe, sim;
|
int bufe, sim;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ts A61007 : All current callers are safe. */
|
/* ts A61007 : All current callers are safe. */
|
||||||
/* a ssert(o->drive == d); */
|
/* a ssert(o->drive == d); */
|
||||||
@ -387,21 +309,11 @@ void spc_select_write_params(struct burn_drive *d,
|
|||||||
|
|
||||||
memset(c.page->data, 0, 8 + 2 + d->mdata->write_page_length);
|
memset(c.page->data, 0, 8 + 2 + d->mdata->write_page_length);
|
||||||
c.page->bytes = 8 + 2 + d->mdata->write_page_length;
|
c.page->bytes = 8 + 2 + d->mdata->write_page_length;
|
||||||
|
|
||||||
burn_print(12, "using write page length %d (valid %d)\n",
|
|
||||||
d->mdata->write_page_length, d->mdata->write_page_valid);
|
|
||||||
|
|
||||||
#ifdef Libburn_mmc_compose_mode_page_5
|
|
||||||
|
|
||||||
/* ts A61229 */
|
|
||||||
if (mmc_compose_mode_page_5(d, o, c.page->data + 8) <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
c.page->data[8] = 5;
|
c.page->data[8] = 5;
|
||||||
c.page->data[9] = d->mdata->write_page_length;
|
c.page->data[9] = d->mdata->write_page_length;
|
||||||
|
|
||||||
|
burn_print(12, "using write page length %d (valid %d)\n",
|
||||||
|
d->mdata->write_page_length, d->mdata->write_page_valid);
|
||||||
bufe = o->underrun_proof;
|
bufe = o->underrun_proof;
|
||||||
sim = o->simulate;
|
sim = o->simulate;
|
||||||
c.page->data[10] = (bufe << 6)
|
c.page->data[10] = (bufe << 6)
|
||||||
@ -420,11 +332,7 @@ void spc_select_write_params(struct burn_drive *d,
|
|||||||
|
|
||||||
c.page->data[22] = 0;
|
c.page->data[22] = 0;
|
||||||
c.page->data[23] = 150; /* audio pause length */
|
c.page->data[23] = 150; /* audio pause length */
|
||||||
|
|
||||||
/*XXX need session format! */
|
/*XXX need session format! */
|
||||||
|
|
||||||
#endif /* ! Libburn_mmc_compose_mode_page_5 */
|
|
||||||
|
|
||||||
c.dir = TO_DRIVE;
|
c.dir = TO_DRIVE;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
}
|
}
|
||||||
@ -434,10 +342,6 @@ void spc_getcaps(struct burn_drive *d)
|
|||||||
spc_inquiry(d);
|
spc_inquiry(d);
|
||||||
spc_sense_caps(d);
|
spc_sense_caps(d);
|
||||||
spc_sense_error_params(d);
|
spc_sense_error_params(d);
|
||||||
|
|
||||||
/* <<< for debugging. >>> ??? to be fixely included here ?
|
|
||||||
mmc_read_format_capacities(d, -1);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -525,8 +429,6 @@ void spc_probe_write_modes(struct burn_drive *d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ( ts A61229 : shouldn't this go to mmc.c too ?) */
|
|
||||||
|
|
||||||
/** @return -1 = error */
|
/** @return -1 = error */
|
||||||
int spc_block_type(enum burn_block_types b)
|
int spc_block_type(enum burn_block_types b)
|
||||||
{
|
{
|
||||||
@ -600,7 +502,6 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
|
|||||||
d->idata->valid = 0;
|
d->idata->valid = 0;
|
||||||
d->mdata = malloc(sizeof(struct scsi_mode_data));
|
d->mdata = malloc(sizeof(struct scsi_mode_data));
|
||||||
d->mdata->valid = 0;
|
d->mdata->valid = 0;
|
||||||
d->mdata->speed_descriptors = NULL;
|
|
||||||
|
|
||||||
/* ts A61007 : obsolete Assert in drive_getcaps() */
|
/* ts A61007 : obsolete Assert in drive_getcaps() */
|
||||||
if(d->idata == NULL || d->mdata == NULL) {
|
if(d->idata == NULL || d->mdata == NULL) {
|
||||||
|
@ -317,8 +317,7 @@ void burn_track_clear_isrc(struct burn_track *t)
|
|||||||
|
|
||||||
int burn_track_get_sectors(struct burn_track *t)
|
int burn_track_get_sectors(struct burn_track *t)
|
||||||
{
|
{
|
||||||
/* ts A70125 : was int */
|
int size;
|
||||||
off_t size;
|
|
||||||
int sectors, seclen;
|
int sectors, seclen;
|
||||||
|
|
||||||
seclen = burn_sector_length(t->mode);
|
seclen = burn_sector_length(t->mode);
|
||||||
@ -330,22 +329,6 @@ int burn_track_get_sectors(struct burn_track *t)
|
|||||||
return sectors;
|
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 */
|
/* ts A61031 */
|
||||||
int burn_track_is_open_ended(struct burn_track *t)
|
int burn_track_is_open_ended(struct burn_track *t)
|
||||||
{
|
{
|
||||||
@ -403,18 +386,12 @@ int burn_disc_get_sectors(struct burn_disc *d)
|
|||||||
|
|
||||||
void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry)
|
void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry)
|
||||||
{
|
{
|
||||||
if (t->entry == NULL)
|
|
||||||
memset(entry, 0, sizeof(struct burn_toc_entry));
|
|
||||||
else
|
|
||||||
memcpy(entry, t->entry, sizeof(struct burn_toc_entry));
|
memcpy(entry, t->entry, sizeof(struct burn_toc_entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
void burn_session_get_leadout_entry(struct burn_session *s,
|
void burn_session_get_leadout_entry(struct burn_session *s,
|
||||||
struct burn_toc_entry *entry)
|
struct burn_toc_entry *entry)
|
||||||
{
|
{
|
||||||
if (s->leadout_entry == NULL)
|
|
||||||
memset(entry, 0, sizeof(struct burn_toc_entry));
|
|
||||||
else
|
|
||||||
memcpy(entry, s->leadout_entry, sizeof(struct burn_toc_entry));
|
memcpy(entry, s->leadout_entry, sizeof(struct burn_toc_entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +88,5 @@ int burn_track_get_shortage(struct burn_track *t);
|
|||||||
int burn_track_is_open_ended(struct burn_track *t);
|
int burn_track_is_open_ended(struct burn_track *t);
|
||||||
int burn_track_is_data_done(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 */
|
#endif /* BURN__STRUCTURE_H */
|
||||||
|
@ -36,12 +36,7 @@ struct params
|
|||||||
|
|
||||||
struct buffer
|
struct buffer
|
||||||
{
|
{
|
||||||
/* ts A61219:
|
unsigned char data[BUFFER_SIZE];
|
||||||
Added 4096 bytes reserve against possible buffer overflows.
|
|
||||||
(Changed in sector.c buffer flush test from >= to > BUFFER_SIZE .
|
|
||||||
This can at most cause a 1 sector overlap. Sometimes an offset
|
|
||||||
of 16 byte is applied to the output data (in some RAW mode). ) */
|
|
||||||
unsigned char data[BUFFER_SIZE + 4096];
|
|
||||||
int sectors;
|
int sectors;
|
||||||
int bytes;
|
int bytes;
|
||||||
};
|
};
|
||||||
@ -65,7 +60,6 @@ struct burn_scsi_inquiry_data
|
|||||||
int valid;
|
int valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct scsi_mode_data
|
struct scsi_mode_data
|
||||||
{
|
{
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
@ -85,12 +79,6 @@ struct scsi_mode_data
|
|||||||
/* ts A61021 */
|
/* ts A61021 */
|
||||||
int min_write_speed;
|
int min_write_speed;
|
||||||
|
|
||||||
/* ts A61225 : Results from ACh GET PERFORMANCE, Type 03h
|
|
||||||
Speed values go into *_*_speed */
|
|
||||||
int min_end_lba;
|
|
||||||
int max_end_lba;
|
|
||||||
struct burn_speed_descriptor *speed_descriptors;
|
|
||||||
|
|
||||||
int cur_read_speed;
|
int cur_read_speed;
|
||||||
int cur_write_speed;
|
int cur_write_speed;
|
||||||
int retry_page_length;
|
int retry_page_length;
|
||||||
@ -103,20 +91,6 @@ struct scsi_mode_data
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ts A70112 : represents a single Formattable Capacity Descriptor as of
|
|
||||||
mmc5r03c.pdf 6.24.3.3 . There can at most be 32 of them. */
|
|
||||||
struct burn_format_descr {
|
|
||||||
/* format type: e.g 0x00 is "Full", 0x15 is "Quick" */
|
|
||||||
int type;
|
|
||||||
|
|
||||||
/* the size in bytes derived from Number of Blocks */
|
|
||||||
off_t size;
|
|
||||||
|
|
||||||
/* the Type Dependent Parameter (usually the write alignment size) */
|
|
||||||
unsigned tdp;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define LIBBURN_SG_MAX_SIBLINGS 16
|
#define LIBBURN_SG_MAX_SIBLINGS 16
|
||||||
|
|
||||||
/** Gets initialized in enumerate_common() and burn_drive_register() */
|
/** Gets initialized in enumerate_common() and burn_drive_register() */
|
||||||
@ -145,50 +119,6 @@ struct burn_drive
|
|||||||
|
|
||||||
enum burn_disc_status status;
|
enum burn_disc_status status;
|
||||||
int erasable;
|
int erasable;
|
||||||
|
|
||||||
/* ts A61201 from 46h GET CONFIGURATION */
|
|
||||||
int current_profile;
|
|
||||||
char current_profile_text[80];
|
|
||||||
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 needs_close_session;
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
int format_descr_type; /* 1=unformatted, 2=formatted, 3=unclear */
|
|
||||||
off_t format_curr_max_size; /* meaning depends on format_descr_type */
|
|
||||||
unsigned format_curr_blsas; /* meaning depends on format_descr_type */
|
|
||||||
int best_format_type;
|
|
||||||
off_t best_format_size;
|
|
||||||
|
|
||||||
/* The complete list of format descriptors as read with 23h */
|
|
||||||
int num_format_descr;
|
|
||||||
struct burn_format_descr format_descriptors[32];
|
|
||||||
|
|
||||||
|
|
||||||
volatile int released;
|
volatile int released;
|
||||||
|
|
||||||
/* ts A61106 */
|
/* ts A61106 */
|
||||||
@ -199,15 +129,6 @@ struct burn_drive
|
|||||||
int rlba; /* relative lba in section */
|
int rlba; /* relative lba in section */
|
||||||
int start_lba;
|
int start_lba;
|
||||||
int end_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;
|
int toc_temp;
|
||||||
struct burn_disc *disc; /* disc structure */
|
struct burn_disc *disc; /* disc structure */
|
||||||
int block_types[4];
|
int block_types[4];
|
||||||
@ -251,19 +172,10 @@ struct burn_drive
|
|||||||
void (*send_write_parameters) (struct burn_drive *,
|
void (*send_write_parameters) (struct burn_drive *,
|
||||||
const struct burn_write_opts *);
|
const struct burn_write_opts *);
|
||||||
void (*send_cue_sheet) (struct burn_drive *, struct cue_sheet *);
|
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 *);
|
void (*sync_cache) (struct burn_drive *);
|
||||||
int (*get_erase_progress) (struct burn_drive *);
|
int (*get_erase_progress) (struct burn_drive *);
|
||||||
int (*get_nwa) (struct burn_drive *, int trackno, int *lba, int *nwa);
|
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 */
|
/* ts A61009 : removed d in favor of o->drive */
|
||||||
/* void (*close_disc) (struct burn_drive * d,
|
/* void (*close_disc) (struct burn_drive * d,
|
||||||
struct burn_write_opts * o);
|
struct burn_write_opts * o);
|
||||||
@ -288,13 +200,6 @@ struct burn_drive
|
|||||||
/* ts A61023 : get size and free space of drive buffer */
|
/* ts A61023 : get size and free space of drive buffer */
|
||||||
int (*read_buffer_capacity) (struct burn_drive *d);
|
int (*read_buffer_capacity) (struct burn_drive *d);
|
||||||
|
|
||||||
/* ts A61220 : format media (e.g. DVD+RW) */
|
|
||||||
int (*format_unit) (struct burn_drive *d, off_t size, int flag);
|
|
||||||
|
|
||||||
/* ts A70108 */
|
|
||||||
/* mmc5r03c.pdf 6.24 : get list of available formats */
|
|
||||||
int (*read_format_capacities) (struct burn_drive *d, int top_wanted);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* end of generic 'drive' data structures */
|
/* end of generic 'drive' data structures */
|
||||||
|
735
libburn/write.c
735
libburn/write.c
@ -195,10 +195,7 @@ 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-1 mentions track number 0xFF for "the incomplete track",
|
||||||
MMC-3 does not. I tried both. 0xFF was in effect when other
|
MMC-3 does not. I tried both. 0xFF was in effect when other
|
||||||
bugs finally gave up and made way for readable tracks. */
|
bugs finally gave up and made way for readable tracks. */
|
||||||
/* ts A70129
|
d->close_track_session(o->drive, 0, 0xff); /* tnum+1); */
|
||||||
Probably the right value for appendables is d->last_track_no
|
|
||||||
*/
|
|
||||||
d->close_track_session(o->drive, 0, 0xff);
|
|
||||||
|
|
||||||
/* ts A61102 */
|
/* ts A61102 */
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
d->busy = BURN_DRIVE_WRITING;
|
||||||
@ -301,7 +298,7 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
|||||||
struct burn_session *session,
|
struct burn_session *session,
|
||||||
int nwa)
|
int nwa)
|
||||||
{
|
{
|
||||||
int i, m, s, f, form, pform, runtime = -150, ret, track_length;
|
int i, m, s, f, form, pform, runtime = -150, ret;
|
||||||
unsigned char ctladr;
|
unsigned char ctladr;
|
||||||
struct burn_drive *d;
|
struct burn_drive *d;
|
||||||
struct burn_toc_entry *e;
|
struct burn_toc_entry *e;
|
||||||
@ -389,22 +386,10 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
|||||||
e[2].control = e[1].control;
|
e[2].control = e[1].control;
|
||||||
e[2].adr = 1;
|
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;
|
tar[0]->pregap2 = 1;
|
||||||
|
|
||||||
pform = form;
|
pform = form;
|
||||||
for (i = 0; i < ntr; i++) {
|
for (i = 0; i < ntr; i++) {
|
||||||
type_to_form(tar[i]->mode, &ctladr, &form);
|
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) {
|
if (pform != form) {
|
||||||
|
|
||||||
ret = add_cue(sheet, ctladr | 1, i + 1, 0, form, 0,
|
ret = add_cue(sheet, ctladr | 1, i + 1, 0, form, 0,
|
||||||
@ -420,21 +405,6 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
|||||||
/ / if (!(form & BURN_AUDIO))
|
/ / if (!(form & BURN_AUDIO))
|
||||||
/ / tar[i]->pregap1 = 1;
|
/ / 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;
|
tar[i]->pregap2 = 1;
|
||||||
}
|
}
|
||||||
/* XXX HERE IS WHERE WE DO INDICES IN THE CUE SHEET */
|
/* XXX HERE IS WHERE WE DO INDICES IN THE CUE SHEET */
|
||||||
@ -454,20 +424,7 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
|||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
/* ts A70125 :
|
runtime += burn_track_get_sectors(tar[i]);
|
||||||
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 padding, we'll clear any current shortage.
|
||||||
if we're not, we'll slip toc entries by a sector every time our
|
if we're not, we'll slip toc entries by a sector every time our
|
||||||
shortage is more than a sector
|
shortage is more than a sector
|
||||||
@ -623,29 +580,6 @@ ex:;
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61218 : outsourced from burn_write_track() */
|
|
||||||
int burn_disc_init_track_status(struct burn_write_opts *o,
|
|
||||||
struct burn_session *s, int tnum, int sectors)
|
|
||||||
{
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
|
|
||||||
/* Update progress */
|
|
||||||
d->progress.start_sector = d->nwa;
|
|
||||||
d->progress.sectors = sectors;
|
|
||||||
d->progress.sector = 0;
|
|
||||||
|
|
||||||
/* ts A60831: added tnum-line, extended print message on proposal
|
|
||||||
by bonfire-app@wanadoo.fr in http://libburn.pykix.org/ticket/58 */
|
|
||||||
d->progress.track = tnum;
|
|
||||||
|
|
||||||
/* ts A61102 */
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
|
int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
|
||||||
int tnum)
|
int tnum)
|
||||||
{
|
{
|
||||||
@ -669,27 +603,12 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
|
|||||||
d->rlba += 150;
|
d->rlba += 150;
|
||||||
|
|
||||||
if (t->pregap1) {
|
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) {
|
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");
|
printf("first track should not have a pregap1\n");
|
||||||
pt = t;
|
pt = t;
|
||||||
} else
|
}
|
||||||
pt = s->track[tnum - 1]; /* ts A70121 */
|
|
||||||
for (i = 0; i < 75; i++)
|
for (i = 0; i < 75; i++)
|
||||||
if (!sector_pregap(o, t->entry->point,
|
if (!sector_pregap(o, t->entry->point,
|
||||||
pt->entry->control, pt->mode))
|
pt->entry->control, pt->mode))
|
||||||
@ -718,10 +637,20 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
|
|||||||
|
|
||||||
/* user data */
|
/* user data */
|
||||||
|
|
||||||
|
/* ts A61102 */
|
||||||
|
d->busy = BURN_DRIVE_WRITING;
|
||||||
|
|
||||||
sectors = burn_track_get_sectors(t);
|
sectors = burn_track_get_sectors(t);
|
||||||
open_ended = burn_track_is_open_ended(t);
|
open_ended = burn_track_is_open_ended(t);
|
||||||
|
|
||||||
burn_disc_init_track_status(o, s, tnum, sectors);
|
/* Update progress */
|
||||||
|
d->progress.start_sector = d->nwa;
|
||||||
|
d->progress.sectors = sectors;
|
||||||
|
d->progress.sector = 0;
|
||||||
|
|
||||||
|
/* ts A60831: added tnum-line, extended print message on proposal
|
||||||
|
by bonfire-app@wanadoo.fr in http://libburn.pykix.org/ticket/58 */
|
||||||
|
d->progress.track = tnum;
|
||||||
|
|
||||||
burn_print(12, "track %d is %d sectors long\n", tnum, sectors);
|
burn_print(12, "track %d is %d sectors long\n", tnum, sectors);
|
||||||
|
|
||||||
@ -832,584 +761,6 @@ bad_track_mode_found:;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61218 : outsourced from burn_disc_write_sync() */
|
|
||||||
int burn_disc_init_write_status(struct burn_write_opts *o,
|
|
||||||
struct burn_disc *disc)
|
|
||||||
{
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
|
|
||||||
d->cancel = 0;
|
|
||||||
|
|
||||||
/* init progress before showing the state */
|
|
||||||
d->progress.session = 0;
|
|
||||||
d->progress.sessions = disc->sessions;
|
|
||||||
d->progress.track = 0;
|
|
||||||
d->progress.tracks = disc->session[0]->tracks;
|
|
||||||
/* TODO: handle indices */
|
|
||||||
d->progress.index = 0;
|
|
||||||
d->progress.indices = disc->session[0]->track[0]->indices;
|
|
||||||
/* TODO: handle multissession discs */
|
|
||||||
/* XXX: sectors are only set during write track */
|
|
||||||
d->progress.start_sector = 0;
|
|
||||||
d->progress.sectors = 0;
|
|
||||||
d->progress.sector = 0;
|
|
||||||
d->progress.track = 0;
|
|
||||||
|
|
||||||
/* ts A61023 */
|
|
||||||
d->progress.buffer_capacity = 0;
|
|
||||||
d->progress.buffer_available = 0;
|
|
||||||
d->progress.buffered_bytes = 0;
|
|
||||||
d->progress.buffer_min_fill = 0xffffffff;
|
|
||||||
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
{
|
|
||||||
struct burn_track *t = s->track[tnum];
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
struct buffer *out = d->buffer;
|
|
||||||
int sectors;
|
|
||||||
int i, open_ended = 0, ret= 0, is_flushed = 0;
|
|
||||||
|
|
||||||
sectors = burn_track_get_sectors(t);
|
|
||||||
open_ended = burn_track_is_open_ended(t);
|
|
||||||
|
|
||||||
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++) {
|
|
||||||
|
|
||||||
/* From time to time inquire drive buffer */
|
|
||||||
if ((i%256)==0)
|
|
||||||
d->read_buffer_capacity(d);
|
|
||||||
|
|
||||||
/* transact a (CD sized) sector */
|
|
||||||
if (!sector_data(o, t, 0))
|
|
||||||
{ ret = 0; goto ex; }
|
|
||||||
|
|
||||||
if (open_ended) {
|
|
||||||
d->progress.sectors = sectors = i;
|
|
||||||
if (burn_track_is_data_done(t))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update current progress */
|
|
||||||
d->progress.sector++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
out->bytes = o->obs;
|
|
||||||
}
|
|
||||||
ret = burn_write_flush(o, t);
|
|
||||||
if (ret <= 0)
|
|
||||||
goto ex;
|
|
||||||
is_flushed = 1;
|
|
||||||
|
|
||||||
/* 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 (!is_flushed)
|
|
||||||
d->sync_cache(d); /* burn_write_flush() was not called */
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61219 */
|
|
||||||
int burn_disc_close_session_dvd_plus_rw(struct burn_write_opts *o,
|
|
||||||
struct burn_session *s)
|
|
||||||
{
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
|
|
||||||
d->busy = BURN_DRIVE_CLOSING_SESSION;
|
|
||||||
/* This seems to be a quick end : "if (!dvd_compat)" */
|
|
||||||
/* >>> Stop de-icing (ongoing background format) quickly
|
|
||||||
by mmc_close() (but with opcode[2]=0).
|
|
||||||
Wait for unit to get ready.
|
|
||||||
return 1;
|
|
||||||
*/
|
|
||||||
/* Else: end eventual background format in a "DVD-RO" compatible way */
|
|
||||||
d->close_track_session(d, 1, 0); /* same as CLOSE SESSION for CD */
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61228 */
|
|
||||||
int burn_disc_close_session_dvd_minus_rw(struct burn_write_opts *o,
|
|
||||||
struct burn_session *s)
|
|
||||||
{
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
|
|
||||||
d->busy = BURN_DRIVE_CLOSING_SESSION;
|
|
||||||
if (d->current_profile == 0x13) {
|
|
||||||
d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
|
|
||||||
|
|
||||||
/* ??? under what circumstances to use close functiom 011b
|
|
||||||
"Finalize disc" ? */
|
|
||||||
|
|
||||||
}
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
{
|
|
||||||
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 == 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->needs_close_session) {
|
|
||||||
ret = burn_disc_close_session_dvd_minus_rw(o, s);
|
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61218 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */
|
|
||||||
int burn_disc_setup_dvd_plus_rw(struct burn_write_opts *o,
|
|
||||||
struct burn_disc *disc)
|
|
||||||
{
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
int ret;
|
|
||||||
char msg[160];
|
|
||||||
|
|
||||||
if (d->bg_format_status==0 || d->bg_format_status==1) {
|
|
||||||
d->busy = BURN_DRIVE_FORMATTING;
|
|
||||||
/* start or re-start dvd_plus_rw formatting */
|
|
||||||
ret = d->format_unit(d, (off_t) 0, 0);
|
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
d->needs_close_session = 1;
|
|
||||||
}
|
|
||||||
d->nwa = 0;
|
|
||||||
if (o->start_byte >= 0) {
|
|
||||||
d->nwa = o->start_byte / 2048;
|
|
||||||
|
|
||||||
sprintf(msg, "Write start address is %d * 2048", d->nwa);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020127,
|
|
||||||
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* >>> perform OPC if needed */;
|
|
||||||
|
|
||||||
/* >>> ? what else ? */;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61228 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */
|
|
||||||
int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
|
|
||||||
struct burn_disc *disc)
|
|
||||||
{
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
char msg[160];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
d->nwa = 0;
|
|
||||||
if (o->start_byte >= 0) {
|
|
||||||
d->nwa = o->start_byte / 32768; /* align to 32 kB */
|
|
||||||
|
|
||||||
sprintf(msg, "Write start address is %d * 32768", d->nwa);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020127,
|
|
||||||
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
|
|
||||||
d->nwa *= 16; /* convert to 2048 block units */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->current_profile == 0x13) { /* DVD-RW restricted overwrite */
|
|
||||||
|
|
||||||
/* ??? mmc5r03c.pdf 7.5.2 :
|
|
||||||
"For DVD-RW media ... If a medium is in Restricted overwrite
|
|
||||||
mode, this mode page shall not be used."
|
|
||||||
|
|
||||||
But growisofs composes a page 5 and sends it.
|
|
||||||
mmc5r03c.pdf 5.3.16 , table 127 specifies that mode page 5
|
|
||||||
shall be supported with feature 0026h Restricted Overwrite.
|
|
||||||
5.3.22 describes a feature 002Ch Rigid Restrictive Overwrite
|
|
||||||
which seems to apply to DVD-RW and does not mention page 5.
|
|
||||||
|
|
||||||
5.4.14 finally states that profile 0013h includes feature
|
|
||||||
002Ch rather than 0026h.
|
|
||||||
|
|
||||||
d->send_write_parameters(d, o);
|
|
||||||
*/
|
|
||||||
|
|
||||||
d->busy = BURN_DRIVE_FORMATTING;
|
|
||||||
|
|
||||||
/* "quick grow" to at least byte equivalent of d->nwa */
|
|
||||||
ret = d->format_unit(d, (off_t) d->nwa * (off_t) 2048,
|
|
||||||
(d->nwa > 0) << 3);
|
|
||||||
if (ret <= 0)
|
|
||||||
return 0;
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
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);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* >>> perform OPC if needed */;
|
|
||||||
|
|
||||||
/* >>> */;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* 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, 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;
|
|
||||||
if (disc->session[sx]->track[tx]->mode != BURN_MODE1)
|
|
||||||
exotic_track = 1;
|
|
||||||
}
|
|
||||||
if (exotic_track) {
|
|
||||||
sprintf(msg,"DVD Media are unsuitable for desired track type");
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020123,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
goto early_failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
|
|
||||||
d->current_profile == 0x12) {
|
|
||||||
/* DVD+RW , DVD-RW Restricted Overwrite , DVD-RAM */
|
|
||||||
if (disc->sessions!=1 || disc->session[0]->tracks>1
|
|
||||||
|| o->multi ) {
|
|
||||||
sprintf(msg,
|
|
||||||
"Burning is restricted to a single track and no multi-session on %s",
|
|
||||||
d->current_profile_text);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x0002011f,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
goto early_failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (d->current_profile == 0x1a || d->current_profile == 0x12) {
|
|
||||||
/* DVD+RW , DVD-RAM */
|
|
||||||
if (o->start_byte >= 0 && (o->start_byte % 2048)) {
|
|
||||||
sprintf(msg,
|
|
||||||
"Write start address not properly aligned to 2048");
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020125,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
goto early_failure;
|
|
||||||
}
|
|
||||||
ret = 1;
|
|
||||||
if (d->current_profile == 0x1a)
|
|
||||||
ret = burn_disc_setup_dvd_plus_rw(o, disc);
|
|
||||||
if (ret <= 0) {
|
|
||||||
sprintf(msg,
|
|
||||||
"Write preparation setup failed for DVD+RW");
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020121,
|
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
goto early_failure;
|
|
||||||
}
|
|
||||||
o->obs_pad = 0; /* no filling-up of track's last 32k buffer */
|
|
||||||
|
|
||||||
} 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");
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020125,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
goto early_failure;
|
|
||||||
}
|
|
||||||
ret = burn_disc_setup_dvd_minus_rw(o, disc);
|
|
||||||
if (ret <= 0) {
|
|
||||||
sprintf(msg,
|
|
||||||
"Write preparation setup failed for DVD-RW");
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x00020121,
|
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
goto early_failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* _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);
|
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
|
||||||
0x0002011e,
|
|
||||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
|
||||||
msg, 0,0);
|
|
||||||
goto early_failure;
|
|
||||||
}
|
|
||||||
o->obs = 32*1024; /* buffer flush trigger for sector.c:get_sector() */
|
|
||||||
|
|
||||||
for (i = 0; i < disc->sessions; i++) {
|
|
||||||
/* update progress */
|
|
||||||
d->progress.session = i;
|
|
||||||
d->progress.tracks = disc->session[i]->tracks;
|
|
||||||
|
|
||||||
ret = burn_dvd_write_session(o, disc->session[i]);
|
|
||||||
if (ret <= 0)
|
|
||||||
goto ex;
|
|
||||||
|
|
||||||
/* XXX: currently signs an end of session */
|
|
||||||
d->progress.sector = 0;
|
|
||||||
d->progress.start_sector = 0;
|
|
||||||
d->progress.sectors = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* >>> eventual normal finalization measures */
|
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
ex:;
|
|
||||||
|
|
||||||
/* >>> eventual emergency finalization measures */
|
|
||||||
|
|
||||||
/* update media state records */
|
|
||||||
burn_drive_mark_unready(d);
|
|
||||||
burn_drive_inquire_media(d);
|
|
||||||
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
|
||||||
return ret;
|
|
||||||
early_failure:;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
|
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
|
||||||
{
|
{
|
||||||
struct cue_sheet *sheet;
|
struct cue_sheet *sheet;
|
||||||
@ -1423,33 +774,14 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
|
|||||||
burn_message_clear_queue();
|
burn_message_clear_queue();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ts A61224 */
|
burn_print(1, "sync write of %d sessions\n", disc->sessions);
|
||||||
burn_disc_init_write_status(o, disc); /* must be done very early */
|
|
||||||
|
|
||||||
d->buffer = &buf;
|
d->buffer = &buf;
|
||||||
memset(d->buffer, 0, sizeof(struct buffer));
|
memset(d->buffer, 0, sizeof(struct buffer));
|
||||||
|
|
||||||
d->rlba = -150;
|
d->rlba = -150;
|
||||||
|
|
||||||
d->toc_temp = 9;
|
d->toc_temp = 9;
|
||||||
|
|
||||||
/* ts A61218 */
|
|
||||||
if (! d->current_is_cd_profile) {
|
|
||||||
ret = burn_dvd_write_sync(o, disc);
|
|
||||||
if (ret <= 0)
|
|
||||||
goto fail_wo_sync;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 fail_wo_sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
burn_print(1, "sync write of %d CD sessions\n", disc->sessions);
|
|
||||||
|
|
||||||
/* Apparently some drives require this command to be sent, and a few drives
|
/* Apparently some drives require this command to be sent, and a few drives
|
||||||
return crap. so we send the command, then ignore the result.
|
return crap. so we send the command, then ignore the result.
|
||||||
*/
|
*/
|
||||||
@ -1471,6 +803,28 @@ return crap. so we send the command, then ignore the result.
|
|||||||
msg,0,0);
|
msg,0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* init progress before showing the state */
|
||||||
|
d->progress.session = 0;
|
||||||
|
d->progress.sessions = disc->sessions;
|
||||||
|
d->progress.track = 0;
|
||||||
|
d->progress.tracks = disc->session[0]->tracks;
|
||||||
|
/* TODO: handle indices */
|
||||||
|
d->progress.index = 0;
|
||||||
|
d->progress.indices = disc->session[0]->track[0]->indices;
|
||||||
|
/* TODO: handle multissession discs */
|
||||||
|
/* XXX: sectors are only set during write track */
|
||||||
|
d->progress.start_sector = 0;
|
||||||
|
d->progress.sectors = 0;
|
||||||
|
d->progress.sector = 0;
|
||||||
|
|
||||||
|
/* ts A61023 */
|
||||||
|
d->progress.buffer_capacity = 0;
|
||||||
|
d->progress.buffer_available = 0;
|
||||||
|
d->progress.buffered_bytes = 0;
|
||||||
|
d->progress.buffer_min_fill = 0xffffffff;
|
||||||
|
|
||||||
|
d->busy = BURN_DRIVE_WRITING;
|
||||||
|
|
||||||
for (i = 0; i < disc->sessions; i++) {
|
for (i = 0; i < disc->sessions; i++) {
|
||||||
/* update progress */
|
/* update progress */
|
||||||
d->progress.session = i;
|
d->progress.session = i;
|
||||||
@ -1566,10 +920,6 @@ return crap. so we send the command, then ignore the result.
|
|||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
/* ts A61125 : update media state records */
|
|
||||||
burn_drive_mark_unready(d);
|
|
||||||
burn_drive_inquire_media(d);
|
|
||||||
|
|
||||||
burn_print(1, "done\n");
|
burn_print(1, "done\n");
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
d->busy = BURN_DRIVE_IDLE;
|
||||||
|
|
||||||
@ -1579,12 +929,9 @@ return crap. so we send the command, then ignore the result.
|
|||||||
|
|
||||||
fail:
|
fail:
|
||||||
d->sync_cache(d);
|
d->sync_cache(d);
|
||||||
fail_wo_sync:;
|
|
||||||
usleep(500001); /* ts A61222: to avoid a warning from remove_worker()*/
|
|
||||||
burn_print(1, "done - failed\n");
|
burn_print(1, "done - failed\n");
|
||||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010b,
|
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002010b,
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
"Burn run failed", 0, 0);
|
"Burn run failed", 0, 0);
|
||||||
d->cancel = 1;
|
|
||||||
d->busy = BURN_DRIVE_IDLE;
|
d->busy = BURN_DRIVE_IDLE;
|
||||||
}
|
}
|
||||||
|
182
test/libburner.c
182
test/libburner.c
@ -7,12 +7,10 @@
|
|||||||
/** Overview
|
/** Overview
|
||||||
|
|
||||||
libburner is a minimal demo application for the library libburn as provided
|
libburner is a minimal demo application for the library libburn as provided
|
||||||
on http://libburnia.pykix.org . It can list the available devices, can
|
on http://libburn.pykix.org . It can list the available devices, can
|
||||||
blank a CD-RW or DVD-RW, can format a DVD-RW, and can burn to CD-R, CD-RW,
|
blank a CD-RW and can burn to CD-R or 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
|
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
|
to serve the libburn team as reference application. libburner.c does indeed
|
||||||
define the standard way how above three gestures can be implemented and
|
define the standard way how above three gestures can be implemented and
|
||||||
stay upward compatible for a good while.
|
stay upward compatible for a good while.
|
||||||
|
|
||||||
@ -27,9 +25,9 @@
|
|||||||
libburner_aquire_by_driveno() demonstrates a scan-and-choose approach
|
libburner_aquire_by_driveno() demonstrates a scan-and-choose approach
|
||||||
With that aquired drive you can blank a CD-RW
|
With that aquired drive you can blank a CD-RW
|
||||||
libburner_blank_disc()
|
libburner_blank_disc()
|
||||||
or you can format a DVD-RW to profile "Restricted Overwrite" (needed once)
|
Between blanking and burning one eventually has to reload the drive status
|
||||||
libburner_format_row()
|
libburner_regrab()
|
||||||
With the aquired drive you can burn to CD-R, CD-RW, DVD+RW, DVD-RAM, DVD-RW
|
With the aquired drive you can burn to CD-R or blank CD-RW
|
||||||
libburner_payload()
|
libburner_payload()
|
||||||
When everything is done, main() releases the drive and shuts down libburn:
|
When everything is done, main() releases the drive and shuts down libburn:
|
||||||
burn_drive_release();
|
burn_drive_release();
|
||||||
@ -72,10 +70,6 @@ static unsigned int drive_count;
|
|||||||
finally released */
|
finally released */
|
||||||
static int drive_is_grabbed = 0;
|
static int drive_is_grabbed = 0;
|
||||||
|
|
||||||
/** A number and a text describing the type of media in aquired drive */
|
|
||||||
static int current_profile= -1;
|
|
||||||
static char current_profile_name[80]= {""};
|
|
||||||
|
|
||||||
|
|
||||||
/* Some in-advance definitions to allow a more comprehensive ordering
|
/* Some in-advance definitions to allow a more comprehensive ordering
|
||||||
of the functions and their explanations in here */
|
of the functions and their explanations in here */
|
||||||
@ -104,13 +98,7 @@ int libburner_aquire_drive(char *drive_adr, int *driveno)
|
|||||||
ret = libburner_aquire_by_adr(drive_adr);
|
ret = libburner_aquire_by_adr(drive_adr);
|
||||||
else
|
else
|
||||||
ret = libburner_aquire_by_driveno(driveno);
|
ret = libburner_aquire_by_driveno(driveno);
|
||||||
if (ret <= 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
burn_disc_get_profile(drive_list[0].drive, ¤t_profile,
|
|
||||||
current_profile_name);
|
|
||||||
if (current_profile_name[0])
|
|
||||||
printf("Detected media type: %s\n", current_profile_name);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -121,21 +109,12 @@ int libburner_aquire_drive(char *drive_adr, int *driveno)
|
|||||||
int libburner_aquire_by_adr(char *drive_adr)
|
int libburner_aquire_by_adr(char *drive_adr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
|
|
||||||
|
|
||||||
/* This tries to resolve links or alternative device files */
|
printf("Aquiring drive '%s' ...\n",drive_adr);
|
||||||
ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);
|
ret = burn_drive_scan_and_grab(&drive_list,drive_adr,1);
|
||||||
if (ret<=0) {
|
|
||||||
fprintf(stderr,"Address does not lead to a CD burner: '%s'\n",
|
|
||||||
drive_adr);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Aquiring drive '%s' ...\n",libburn_drive_adr);
|
|
||||||
ret = burn_drive_scan_and_grab(&drive_list,libburn_drive_adr,1);
|
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
|
fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
|
||||||
libburn_drive_adr);
|
drive_adr);
|
||||||
} else {
|
} else {
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
drive_is_grabbed = 1;
|
drive_is_grabbed = 1;
|
||||||
@ -262,17 +241,19 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
|
|||||||
{
|
{
|
||||||
enum burn_disc_status disc_state;
|
enum burn_disc_status disc_state;
|
||||||
struct burn_progress p;
|
struct burn_progress p;
|
||||||
double percent = 1.0;
|
int percent = 1;
|
||||||
|
|
||||||
disc_state = burn_disc_get_status(drive);
|
while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
|
||||||
|
usleep(1001);
|
||||||
|
|
||||||
|
while ((disc_state = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
|
||||||
|
usleep(1001);
|
||||||
printf(
|
printf(
|
||||||
"Drive media status: %d (see libburn/libburn.h BURN_DISC_*)\n",
|
"Drive media status: %d (see libburn/libburn.h BURN_DISC_*)\n",
|
||||||
disc_state);
|
disc_state);
|
||||||
if (current_profile == 0x13) {
|
if (disc_state == BURN_DISC_BLANK) {
|
||||||
; /* formatted DVD-RW will get blanked to sequential state */
|
|
||||||
} else if (disc_state == BURN_DISC_BLANK) {
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"IDLE: Blank media detected. Will leave it untouched\n");
|
"IDLE: Blank CD media detected. Will leave it untouched\n");
|
||||||
return 2;
|
return 2;
|
||||||
} else if (disc_state == BURN_DISC_FULL ||
|
} else if (disc_state == BURN_DISC_FULL ||
|
||||||
disc_state == BURN_DISC_APPENDABLE) {
|
disc_state == BURN_DISC_APPENDABLE) {
|
||||||
@ -282,7 +263,7 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"FATAL: Unsuitable drive and media state\n");
|
"FATAL: Cannot recognize drive and media state\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(!burn_disc_erasable(drive)) {
|
if(!burn_disc_erasable(drive)) {
|
||||||
@ -291,14 +272,14 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
printf(
|
printf(
|
||||||
"Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
|
"Beginning to %s-blank CD media.\n", (blank_fast?"fast":"full"));
|
||||||
burn_disc_erase(drive, blank_fast);
|
burn_disc_erase(drive, blank_fast);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
|
while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
|
||||||
if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
|
if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
|
||||||
percent = 1.0 + ((double) p.sector+1.0)
|
percent = 1.0 + ((double) p.sector+1.0)
|
||||||
/ ((double) p.sectors) * 98.0;
|
/ ((double) p.sectors) * 98.0;
|
||||||
printf("Blanking ( %.1f%% done )\n", percent);
|
printf("Blanking ( %d%% done )\n", percent);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
@ -306,44 +287,24 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Persistently changes DVD-RW profile 0014h "Sequential Recording"
|
/** This gesture is necessary to get the drive info after blanking.
|
||||||
to profile 0013h "Restricted Overwrite" which is usable with libburner.
|
It opens a small gap for losing the drive to another libburn instance.
|
||||||
|
We will work on closing this gap.
|
||||||
Expect a behavior similar to blanking with unusual noises from the drive.
|
|
||||||
*/
|
*/
|
||||||
int libburner_format_row(struct burn_drive *drive)
|
int libburner_regrab(struct burn_drive *drive) {
|
||||||
{
|
int ret;
|
||||||
struct burn_progress p;
|
|
||||||
double percent = 1.0;
|
|
||||||
|
|
||||||
if (current_profile == 0x13) {
|
printf("Releasing and regrabbing drive ...\n");
|
||||||
fprintf(stderr, "IDLE: DVD-RW media is already formatted\n");
|
if (drive_is_grabbed)
|
||||||
return 2;
|
burn_drive_release(drive, 0);
|
||||||
} else if (current_profile != 0x14) {
|
drive_is_grabbed = 0;
|
||||||
fprintf(stderr, "FATAL: Can only format DVD-RW\n");
|
ret = burn_drive_grab(drive, 0);
|
||||||
return 0;
|
if (ret != 0) {
|
||||||
}
|
drive_is_grabbed = 1;
|
||||||
printf("Beginning to format media.\n");
|
printf("Done\n");
|
||||||
burn_disc_format(drive, (off_t) 0, 0);
|
} else
|
||||||
|
printf("FAILED\n");
|
||||||
sleep(1);
|
return !!ret;
|
||||||
while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
|
|
||||||
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 ( %.1f%% done )\n", percent);
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
burn_disc_get_profile(drive_list[0].drive, ¤t_profile,
|
|
||||||
current_profile_name);
|
|
||||||
printf("Media type now: %4.4xh \"%s\"\n",
|
|
||||||
current_profile, current_profile_name);
|
|
||||||
if (current_profile != 0x13) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"FATAL: Failed to change media profile to desired value\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -354,9 +315,6 @@ int libburner_format_row(struct burn_drive *drive)
|
|||||||
|
|
||||||
In case of external signals expect abort handling of an ongoing burn to
|
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.
|
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,
|
int libburner_payload(struct burn_drive *drive,
|
||||||
char source_adr[][4096], int source_adr_count,
|
char source_adr[][4096], int source_adr_count,
|
||||||
@ -370,9 +328,9 @@ int libburner_payload(struct burn_drive *drive,
|
|||||||
struct burn_track *track, *tracklist[99];
|
struct burn_track *track, *tracklist[99];
|
||||||
struct burn_progress progress;
|
struct burn_progress progress;
|
||||||
time_t start_time;
|
time_t start_time;
|
||||||
int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd;
|
int last_sector = 0, padding = 0, trackno, write_mode_tao = 0, fd;
|
||||||
off_t fixed_size;
|
off_t fixed_size;
|
||||||
char *adr, reasons[1024];
|
char *adr;
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
|
|
||||||
if (all_tracks_type != BURN_AUDIO) {
|
if (all_tracks_type != BURN_AUDIO) {
|
||||||
@ -401,7 +359,7 @@ int libburner_payload(struct burn_drive *drive,
|
|||||||
fixed_size = stbuf.st_size;
|
fixed_size = stbuf.st_size;
|
||||||
}
|
}
|
||||||
if (fixed_size==0)
|
if (fixed_size==0)
|
||||||
unpredicted_size = 1;
|
write_mode_tao = 1;
|
||||||
data_src = NULL;
|
data_src = NULL;
|
||||||
if (fd>=0)
|
if (fd>=0)
|
||||||
data_src = burn_fd_source_new(fd, -1, fixed_size);
|
data_src = burn_fd_source_new(fd, -1, fixed_size);
|
||||||
@ -419,14 +377,19 @@ int libburner_payload(struct burn_drive *drive,
|
|||||||
}
|
}
|
||||||
|
|
||||||
burn_session_add_track(session, track, BURN_POS_END);
|
burn_session_add_track(session, track, BURN_POS_END);
|
||||||
printf("Track %d : source is '%s'\n", trackno+1, adr);
|
printf("Track %d : source is '%s'\n", trackno, adr);
|
||||||
burn_source_free(data_src);
|
burn_source_free(data_src);
|
||||||
} /* trackno loop end */
|
} /* trackno loop end */
|
||||||
|
|
||||||
|
while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
|
||||||
|
usleep(100001);
|
||||||
|
|
||||||
/* Evaluate drive and media */
|
/* Evaluate drive and media */
|
||||||
disc_state = burn_disc_get_status(drive);
|
while ((disc_state = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
|
||||||
if (disc_state != BURN_DISC_BLANK &&
|
usleep(100001);
|
||||||
disc_state != BURN_DISC_APPENDABLE) {
|
if (disc_state == BURN_DISC_APPENDABLE) {
|
||||||
|
write_mode_tao = 1;
|
||||||
|
} else if (disc_state != BURN_DISC_BLANK) {
|
||||||
if (disc_state == BURN_DISC_FULL) {
|
if (disc_state == BURN_DISC_FULL) {
|
||||||
fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n");
|
fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n");
|
||||||
if (burn_disc_erasable(drive))
|
if (burn_disc_erasable(drive))
|
||||||
@ -442,17 +405,18 @@ int libburner_payload(struct burn_drive *drive,
|
|||||||
burn_options = burn_write_opts_new(drive);
|
burn_options = burn_write_opts_new(drive);
|
||||||
burn_write_opts_set_perform_opc(burn_options, 0);
|
burn_write_opts_set_perform_opc(burn_options, 0);
|
||||||
burn_write_opts_set_multi(burn_options, !!multi);
|
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)
|
if(simulate_burn)
|
||||||
printf("\n*** Will TRY to SIMULATE burning ***\n\n");
|
printf("\n*** Will TRY to SIMULATE burning ***\n\n");
|
||||||
burn_write_opts_set_simulate(burn_options, simulate_burn);
|
burn_write_opts_set_simulate(burn_options, simulate_burn);
|
||||||
|
burn_structure_print_disc(target_disc);
|
||||||
burn_drive_set_speed(drive, 0, 0);
|
burn_drive_set_speed(drive, 0, 0);
|
||||||
burn_write_opts_set_underrun_proof(burn_options, 1);
|
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");
|
printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
|
||||||
start_time = time(0);
|
start_time = time(0);
|
||||||
@ -466,7 +430,7 @@ int libburner_payload(struct burn_drive *drive,
|
|||||||
printf(
|
printf(
|
||||||
"Thank you for being patient since %d seconds.\n",
|
"Thank you for being patient since %d seconds.\n",
|
||||||
(int) (time(0) - start_time));
|
(int) (time(0) - start_time));
|
||||||
else if(unpredicted_size)
|
else if(write_mode_tao)
|
||||||
printf("Track %d : sector %d\n", progress.track+1,
|
printf("Track %d : sector %d\n", progress.track+1,
|
||||||
progress.sector);
|
progress.sector);
|
||||||
else
|
else
|
||||||
@ -481,12 +445,11 @@ int libburner_payload(struct burn_drive *drive,
|
|||||||
burn_track_free(tracklist[trackno]);
|
burn_track_free(tracklist[trackno]);
|
||||||
burn_session_free(session);
|
burn_session_free(session);
|
||||||
burn_disc_free(target_disc);
|
burn_disc_free(target_disc);
|
||||||
if (multi && current_profile != 0x1a && current_profile != 0x13 &&
|
if (multi)
|
||||||
current_profile != 0x12) /* not with DVD+RW, DVD-RW, DVD-RAM */
|
|
||||||
printf("NOTE: Media left appendable.\n");
|
printf("NOTE: Media left appendable.\n");
|
||||||
if (simulate_burn)
|
if (simulate_burn)
|
||||||
printf("\n*** Did TRY to SIMULATE burning ***\n\n");
|
printf("\n*** Did TRY to SIMULATE burning ***\n\n");
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -541,9 +504,6 @@ int libburner_setup(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
strcpy(drive_adr, argv[i]);
|
strcpy(drive_adr, argv[i]);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[i], "--format_overwrite")) {
|
|
||||||
do_blank = 101;
|
|
||||||
|
|
||||||
} else if (!strcmp(argv[i], "--multi")) {
|
} else if (!strcmp(argv[i], "--multi")) {
|
||||||
do_multi = 1;
|
do_multi = 1;
|
||||||
|
|
||||||
@ -582,8 +542,7 @@ int libburner_setup(int argc, char **argv)
|
|||||||
if (print_help || insuffient_parameters ) {
|
if (print_help || insuffient_parameters ) {
|
||||||
printf("Usage: %s\n", argv[0]);
|
printf("Usage: %s\n", argv[0]);
|
||||||
printf(" [--drive <address>|<driveno>|\"-\"] [--audio]\n");
|
printf(" [--drive <address>|<driveno>|\"-\"] [--audio]\n");
|
||||||
printf(" [--blank_fast|--blank_full|--format_overwrite]\n");
|
printf(" [--blank_fast|--blank_full] [--try_to_simulate]\n");
|
||||||
printf(" [--try_to_simulate]\n");
|
|
||||||
printf(" [--multi] [<one or more imagefiles>|\"-\"]\n");
|
printf(" [--multi] [<one or more imagefiles>|\"-\"]\n");
|
||||||
printf("Examples\n");
|
printf("Examples\n");
|
||||||
printf("A bus scan (needs rw-permissions to see a drive):\n");
|
printf("A bus scan (needs rw-permissions to see a drive):\n");
|
||||||
@ -594,18 +553,15 @@ int libburner_setup(int argc, char **argv)
|
|||||||
printf(" %s --drive /dev/hdc my_image_file\n", argv[0]);
|
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("Blank a used CD-RW (is combinable with burning in one run):\n");
|
||||||
printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]);
|
printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]);
|
||||||
printf("Blank a used DVD-RW (is combinable with burning in one run):\n");
|
printf("Burn two audio tracks\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 (to CD only):\n");
|
|
||||||
printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n");
|
printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n");
|
||||||
printf(" test/dewav /path/to/track2.wav -o track2.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]);
|
printf(" %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]);
|
||||||
printf("Burn a compressed afio archive on-the-fly:\n");
|
printf("Burn a compressed afio archive on-the-fly:\n");
|
||||||
printf(" ( cd my_directory ; find . -print | afio -oZ - ) | \\\n");
|
printf(" ( cd my_directory ; find . -print | afio -oZ - ) | \\\n");
|
||||||
printf(" %s --drive /dev/hdc -\n", argv[0]);
|
printf(" %s --drive /dev/hdc -\n", argv[0]);
|
||||||
printf("To be read from *not mounted* media via: afio -tvZ /dev/hdc\n");
|
printf("To be read from *not mounted* CD via: afio -tvZ /dev/hdc\n");
|
||||||
|
printf("Program tar would need a clean EOF which our padded CD cannot deliver.\n");
|
||||||
if (insuffient_parameters)
|
if (insuffient_parameters)
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
@ -621,7 +577,7 @@ int main(int argc, char **argv)
|
|||||||
if (ret)
|
if (ret)
|
||||||
exit(ret);
|
exit(ret);
|
||||||
|
|
||||||
printf("Initializing libburnia.pykix.org ...\n");
|
printf("Initializing libburn.pykix.org ...\n");
|
||||||
if (burn_initialize())
|
if (burn_initialize())
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
else {
|
else {
|
||||||
@ -646,13 +602,17 @@ int main(int argc, char **argv)
|
|||||||
if (ret == 2)
|
if (ret == 2)
|
||||||
{ ret = 0; goto release_drive; }
|
{ ret = 0; goto release_drive; }
|
||||||
if (do_blank) {
|
if (do_blank) {
|
||||||
if (do_blank > 100)
|
|
||||||
ret = libburner_format_row(drive_list[driveno].drive);
|
|
||||||
else
|
|
||||||
ret = libburner_blank_disc(drive_list[driveno].drive,
|
ret = libburner_blank_disc(drive_list[driveno].drive,
|
||||||
do_blank == 1);
|
do_blank == 1);
|
||||||
if (ret<=0)
|
if (ret<=0)
|
||||||
{ ret = 36; goto release_drive; }
|
{ ret = 36; goto release_drive; }
|
||||||
|
if (ret != 2 && source_adr_count > 0)
|
||||||
|
ret = libburner_regrab(drive_list[driveno].drive);
|
||||||
|
if (ret<=0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"FATAL: Cannot release and grab again drive after blanking\n");
|
||||||
|
{ ret = 37; goto finish_libburn; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (source_adr_count > 0) {
|
if (source_adr_count > 0) {
|
||||||
ret = libburner_payload(drive_list[driveno].drive,
|
ret = libburner_payload(drive_list[driveno].drive,
|
||||||
@ -685,7 +645,7 @@ Be also invited to study the code of cdrskin/cdrskin.c et al.
|
|||||||
|
|
||||||
|
|
||||||
Clarification in my name and in the name of Mario Danic, copyright holder
|
Clarification in my name and in the name of Mario Danic, copyright holder
|
||||||
on toplevel of libburnia. To be fully in effect after the remaining other
|
on toplevel of libburn. To be fully in effect after the remaining other
|
||||||
copyrighted code has been replaced by ours and by copyright-free contributions
|
copyrighted code has been replaced by ours and by copyright-free contributions
|
||||||
of our friends:
|
of our friends:
|
||||||
|
|
||||||
|
302
test/telltoc.c
302
test/telltoc.c
@ -5,9 +5,9 @@
|
|||||||
/** Overview
|
/** Overview
|
||||||
|
|
||||||
telltoc is a minimal demo application for the library libburn as provided
|
telltoc is a minimal demo application for the library libburn as provided
|
||||||
on http://libburnia.pykix.org . It can list the available devices, can
|
on http://libburn.pykix.org . It can list the available devices, can display
|
||||||
display some drive properties, the type of media, eventual table of content
|
some drive properties, the type of media, eventual table of content and
|
||||||
and multisession info for mkisofs option -C .
|
multisession info for mkisofs option -C .
|
||||||
It's main purpose, nevertheless, is to show you how to use libburn and also
|
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
|
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
|
define the standard way how above gestures can be implemented and stay upward
|
||||||
@ -105,20 +105,11 @@ int telltoc_aquire_by_adr(char *drive_adr)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
|
fprintf(stderr,"Aquiring drive '%s' ...\n",drive_adr);
|
||||||
|
ret = burn_drive_scan_and_grab(&drive_list,drive_adr,1);
|
||||||
/* This tries to resolve links or alternative device files */
|
|
||||||
ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);
|
|
||||||
if (ret<=0) {
|
|
||||||
fprintf(stderr,"Address does not lead to a CD burner: '%s'\n",
|
|
||||||
drive_adr);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
fprintf(stderr,"Aquiring drive '%s' ...\n",libburn_drive_adr);
|
|
||||||
ret = burn_drive_scan_and_grab(&drive_list,libburn_drive_adr,1);
|
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
|
fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
|
||||||
libburn_drive_adr);
|
drive_adr);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,"Done\n");
|
fprintf(stderr,"Done\n");
|
||||||
drive_is_grabbed = 1;
|
drive_is_grabbed = 1;
|
||||||
@ -224,33 +215,16 @@ int telltoc_regrab(struct burn_drive *drive) {
|
|||||||
|
|
||||||
int telltoc_media(struct burn_drive *drive)
|
int telltoc_media(struct burn_drive *drive)
|
||||||
{
|
{
|
||||||
int ret, media_found = 0, profile_no = -1;
|
int ret, media_found = 0;
|
||||||
double max_speed = 0.0, min_speed = 0.0, speed_conv;
|
double max_speed = 0.0, min_speed = 0.0;
|
||||||
enum burn_disc_status s;
|
enum burn_disc_status s;
|
||||||
char profile_name[80], speed_unit[40];
|
|
||||||
struct burn_multi_caps *caps;
|
|
||||||
|
|
||||||
printf("Media current: ");
|
while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
|
||||||
ret = burn_disc_get_profile(drive, &profile_no, profile_name);
|
usleep(100001);
|
||||||
if (profile_no > 0 && ret >0) {
|
while ((s = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
|
||||||
if (profile_name[0])
|
usleep(100001);
|
||||||
printf("%s\n", profile_name);
|
|
||||||
else
|
|
||||||
printf("%4.4Xh\n", profile_no);
|
|
||||||
} else
|
|
||||||
printf("is not recognizable\n");
|
|
||||||
|
|
||||||
speed_conv = 176.4;
|
|
||||||
strcpy(speed_unit,"176.4 kB/s (CD, data speed 150 KiB/s)");
|
|
||||||
if (strstr(profile_name, "DVD") == profile_name) {
|
|
||||||
speed_conv = 1385.0;
|
|
||||||
strcpy(speed_unit,"1385.0 kB/s (DVD)");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* >>> libburn does not obtain full profile list yet */
|
|
||||||
|
|
||||||
printf("Media status : ");
|
printf("Media status : ");
|
||||||
s = burn_disc_get_status(drive);
|
|
||||||
if (s==BURN_DISC_FULL) {
|
if (s==BURN_DISC_FULL) {
|
||||||
printf("is written , is closed\n");
|
printf("is written , is closed\n");
|
||||||
media_found = 1;
|
media_found = 1;
|
||||||
@ -265,7 +239,7 @@ int telltoc_media(struct burn_drive *drive)
|
|||||||
else
|
else
|
||||||
printf("is not recognizable\n");
|
printf("is not recognizable\n");
|
||||||
|
|
||||||
printf("Media reuse : ");
|
printf("Media type : ");
|
||||||
if (media_found) {
|
if (media_found) {
|
||||||
if (burn_disc_erasable(drive))
|
if (burn_disc_erasable(drive))
|
||||||
printf("is erasable\n");
|
printf("is erasable\n");
|
||||||
@ -274,154 +248,41 @@ int telltoc_media(struct burn_drive *drive)
|
|||||||
} else
|
} else
|
||||||
printf("is not recognizable\n");
|
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);
|
|
||||||
min_speed = ((double ) ret) / speed_conv;
|
|
||||||
if (!media_found)
|
|
||||||
printf("Drive speed : max=%.1f , min=%.1f\n",
|
|
||||||
max_speed, min_speed);
|
|
||||||
else
|
|
||||||
printf("Avail. speed : max=%.1f , min=%.1f\n",
|
|
||||||
max_speed, min_speed);
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
if (media_found)
|
|
||||||
ret= burn_disc_read_atip(drive);
|
ret= burn_disc_read_atip(drive);
|
||||||
if(ret>0) {
|
if(ret>0) {
|
||||||
ret= burn_drive_get_min_write_speed(drive);
|
ret= burn_drive_get_min_write_speed(drive);
|
||||||
min_speed = ((double ) ret) / speed_conv;
|
min_speed = ((double ) ret) / 176.0;
|
||||||
|
}
|
||||||
ret= burn_drive_get_write_speed(drive);
|
ret= burn_drive_get_write_speed(drive);
|
||||||
max_speed = ((double ) ret) / speed_conv;
|
max_speed = ((double ) ret) / 176.0;
|
||||||
printf("Media speed : max=%.1f , min=%.1f\n",
|
if (!media_found)
|
||||||
max_speed, min_speed);
|
printf("Drive speed : max=%.f\n", max_speed);
|
||||||
}
|
else if (min_speed<=0)
|
||||||
printf("Speed unit 1x: %s\n", speed_unit);
|
printf("Media speed : max=%.f\n", max_speed);
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int telltoc_speedlist(struct burn_drive *drive)
|
|
||||||
{
|
|
||||||
int ret, has_modern_entries = 0;
|
|
||||||
struct burn_speed_descriptor *speed_list, *sd;
|
|
||||||
|
|
||||||
ret = burn_drive_get_speedlist(drive, &speed_list);
|
|
||||||
if (ret <= 0) {
|
|
||||||
fprintf(stderr, "SORRY: Cannot obtain speed list info\n");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
for (sd = speed_list; sd != NULL; sd = sd->next)
|
|
||||||
if (sd->source == 2)
|
|
||||||
has_modern_entries = 1;
|
|
||||||
for (sd = speed_list; sd != NULL; sd = sd->next) {
|
|
||||||
if (has_modern_entries && sd->source < 2)
|
|
||||||
continue;
|
|
||||||
if (sd->write_speed <= 0)
|
|
||||||
continue;
|
|
||||||
printf("Speed descr. : %d kB/s", sd->write_speed);
|
|
||||||
if (sd->end_lba >= 0)
|
|
||||||
printf(", %.1f MiB", ((double) sd->end_lba) / 512.0);
|
|
||||||
if (sd->profile_name[0])
|
|
||||||
printf(", %s", sd->profile_name);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
burn_drive_free_speedlist(&speed_list);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int telltoc_formatlist(struct burn_drive *drive)
|
|
||||||
{
|
|
||||||
int ret, i, status, num_formats, profile_no, type;
|
|
||||||
off_t size;
|
|
||||||
unsigned dummy;
|
|
||||||
char status_text[80], profile_name[90];
|
|
||||||
|
|
||||||
ret = burn_disc_get_formats(drive, &status, &size, &dummy,
|
|
||||||
&num_formats);
|
|
||||||
if (ret <= 0) {
|
|
||||||
fprintf(stderr, "SORRY: Cannot obtain format list info\n");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if (status == BURN_FORMAT_IS_UNFORMATTED)
|
|
||||||
sprintf(status_text, "unformatted, up to %.1f MiB",
|
|
||||||
((double) size) / 1024.0 / 1024.0);
|
|
||||||
else if(status == BURN_FORMAT_IS_FORMATTED)
|
|
||||||
sprintf(status_text, "formatted, with %.1f MiB",
|
|
||||||
((double) size) / 1024.0 / 1024.0);
|
|
||||||
else if(status == BURN_FORMAT_IS_UNKNOWN) {
|
|
||||||
burn_disc_get_profile(drive, &profile_no, profile_name);
|
|
||||||
if (profile_no > 0)
|
|
||||||
sprintf(status_text, "intermediate or unknown");
|
|
||||||
else
|
else
|
||||||
sprintf(status_text, "no media or unknown media");
|
printf("Media speed : max=%.f , min=%.f\n",
|
||||||
} else
|
max_speed, min_speed);
|
||||||
sprintf(status_text, "illegal status according to MMC-5");
|
|
||||||
printf("Format status: %s\n", status_text);
|
|
||||||
|
|
||||||
for (i = 0; i < num_formats; i++) {
|
|
||||||
ret = burn_disc_get_format_descr(drive, i,
|
|
||||||
&type, &size, &dummy);
|
|
||||||
if (ret <= 0)
|
|
||||||
continue;
|
|
||||||
printf("Format descr.: %2.2Xh , %.1f MiB (%.fs)\n",
|
|
||||||
type, ((double) size) / 1024.0 / 1024.0,
|
|
||||||
((double) size) / 2048.0);
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int telltoc_toc(struct burn_drive *drive)
|
int telltoc_toc(struct burn_drive *drive)
|
||||||
{
|
{
|
||||||
int num_sessions = 0 , num_tracks = 0 , lba = 0, pmin, psec, pframe;
|
int num_sessions = 0 , num_tracks = 0 , lba = 0;
|
||||||
int track_count = 0;
|
int track_count = 0;
|
||||||
int session_no, track_no;
|
int session_no, track_no;
|
||||||
|
enum burn_disc_status s;
|
||||||
struct burn_disc *disc= NULL;
|
struct burn_disc *disc= NULL;
|
||||||
struct burn_session **sessions;
|
struct burn_session **sessions;
|
||||||
struct burn_track **tracks;
|
struct burn_track **tracks;
|
||||||
struct burn_toc_entry toc_entry;
|
struct burn_toc_entry toc_entry;
|
||||||
|
|
||||||
|
while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
|
||||||
|
usleep(100001);
|
||||||
|
while ((s = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
|
||||||
|
usleep(100001);
|
||||||
|
|
||||||
disc = burn_drive_get_disc(drive);
|
disc = burn_drive_get_disc(drive);
|
||||||
if (disc==NULL) {
|
if (disc==NULL) {
|
||||||
fprintf(stderr, "SORRY: Cannot obtain Table Of Content\n");
|
fprintf(stderr, "SORRY: Cannot obtain Table Of Content\n");
|
||||||
@ -436,36 +297,27 @@ int telltoc_toc(struct burn_drive *drive)
|
|||||||
for(track_no= 0; track_no<num_tracks; track_no++) {
|
for(track_no= 0; track_no<num_tracks; track_no++) {
|
||||||
track_count++;
|
track_count++;
|
||||||
burn_track_get_entry(tracks[track_no], &toc_entry);
|
burn_track_get_entry(tracks[track_no], &toc_entry);
|
||||||
if (toc_entry.extensions_valid & 1) {
|
lba= burn_msf_to_lba(toc_entry.pmin, toc_entry.psec,
|
||||||
/* DVD extension valid */
|
toc_entry.pframe);
|
||||||
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("Media content: session %2d ", session_no+1);
|
||||||
printf("track %2d %s lba: %9d %4.2d:%2.2d:%2.2d\n",
|
printf("track %2d %s lba: %9d %2.2u:%2.2u:%2.2u\n",
|
||||||
track_count,
|
track_count,
|
||||||
((toc_entry.control&7)<4?"audio":"data "),
|
((toc_entry.control&7)<4?"audio":"data "),
|
||||||
lba, pmin, psec, pframe);
|
lba,
|
||||||
|
toc_entry.pmin,
|
||||||
|
toc_entry.psec,
|
||||||
|
toc_entry.pframe);
|
||||||
}
|
}
|
||||||
burn_session_get_leadout_entry(sessions[session_no],
|
burn_session_get_leadout_entry(sessions[session_no],
|
||||||
&toc_entry);
|
&toc_entry);
|
||||||
if (toc_entry.extensions_valid & 1) {
|
lba = burn_msf_to_lba(toc_entry.pmin,
|
||||||
lba = toc_entry.start_lba;
|
toc_entry.psec, toc_entry.pframe);
|
||||||
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("Media content: session %2d ", session_no+1);
|
||||||
printf("leadout lba: %9d %4.2d:%2.2d:%2.2d\n",
|
printf("leadout lba: %9d %2.2u:%2.2u:%2.2u\n",
|
||||||
lba, pmin, psec, pframe);
|
lba,
|
||||||
|
toc_entry.pmin,
|
||||||
|
toc_entry.psec,
|
||||||
|
toc_entry.pframe);
|
||||||
}
|
}
|
||||||
if (disc!=NULL)
|
if (disc!=NULL)
|
||||||
burn_disc_free(disc);
|
burn_disc_free(disc);
|
||||||
@ -476,11 +328,19 @@ int telltoc_toc(struct burn_drive *drive)
|
|||||||
int telltoc_msinfo(struct burn_drive *drive,
|
int telltoc_msinfo(struct burn_drive *drive,
|
||||||
int msinfo_explicit, int msinfo_alone)
|
int msinfo_explicit, int msinfo_alone)
|
||||||
{
|
{
|
||||||
int ret, lba, nwa = -123456789, aux_lba;
|
int num_sessions, session_no, ret, num_tracks;
|
||||||
|
int nwa = -123456789, lba = -123456789, aux_lba, lout_lba;
|
||||||
enum burn_disc_status s;
|
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;
|
struct burn_write_opts *o= NULL;
|
||||||
|
|
||||||
s = burn_disc_get_status(drive);
|
while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
|
||||||
|
usleep(100001);
|
||||||
|
while ((s = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
|
||||||
|
usleep(100001);
|
||||||
if (s!=BURN_DISC_APPENDABLE) {
|
if (s!=BURN_DISC_APPENDABLE) {
|
||||||
if (!msinfo_explicit)
|
if (!msinfo_explicit)
|
||||||
return 2;
|
return 2;
|
||||||
@ -493,12 +353,29 @@ int telltoc_msinfo(struct burn_drive *drive,
|
|||||||
The first number is the sector number of the first sector in
|
The first number is the sector number of the first sector in
|
||||||
the last session of the disk that should be appended to.
|
the last session of the disk that should be appended to.
|
||||||
*/
|
*/
|
||||||
ret = burn_disc_get_msc1(drive, &lba);
|
disc = burn_drive_get_disc(drive);
|
||||||
if (ret <= 0) {
|
if (disc==NULL) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,"SORRY: Cannot obtain info about CD content\n");
|
||||||
"SORRY: Cannot obtain start address of last session\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 = 0; goto ex; }
|
{ 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 :
|
/* man mkisofs , option -C :
|
||||||
The second number is the starting sector number of the new session.
|
The second number is the starting sector number of the new session.
|
||||||
@ -515,15 +392,21 @@ int telltoc_msinfo(struct burn_drive *drive,
|
|||||||
telltoc_regrab(drive); /* necessary to calm down my NEC drive */
|
telltoc_regrab(drive); /* necessary to calm down my NEC drive */
|
||||||
if(ret<=0) {
|
if(ret<=0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"SORRY: Cannot obtain next writeable address\n");
|
"NOTE: Guessing next writeable address from leadout\n");
|
||||||
{ ret = 0; goto ex; }
|
if(num_sessions>0)
|
||||||
|
nwa= lout_lba+6900;
|
||||||
|
else
|
||||||
|
nwa= lout_lba+11400;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!msinfo_alone)
|
if (!msinfo_alone)
|
||||||
printf("Media msinfo : mkisofs ... -C ");
|
printf("Media msinfo : mkisofs ... -C ");
|
||||||
printf("%d,%d\n",lba,nwa);
|
printf("%d,%d\n",lba,nwa);
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
ex:;
|
ex:;
|
||||||
|
if (disc!=NULL)
|
||||||
|
burn_disc_free(disc);
|
||||||
if (o!=NULL)
|
if (o!=NULL)
|
||||||
burn_write_opts_free(o);
|
burn_write_opts_free(o);
|
||||||
return ret;
|
return ret;
|
||||||
@ -537,7 +420,6 @@ static int do_media = 0;
|
|||||||
static int do_toc = 0;
|
static int do_toc = 0;
|
||||||
static int do_msinfo = 0;
|
static int do_msinfo = 0;
|
||||||
static int print_help = 0;
|
static int print_help = 0;
|
||||||
static int do_capacities = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/** Converts command line arguments into above setup parameters.
|
/** Converts command line arguments into above setup parameters.
|
||||||
@ -574,9 +456,6 @@ int telltoc_setup(int argc, char **argv)
|
|||||||
} else if (!strcmp(argv[i], "--msinfo")) {
|
} else if (!strcmp(argv[i], "--msinfo")) {
|
||||||
do_msinfo = 1;
|
do_msinfo = 1;
|
||||||
|
|
||||||
} else if (!strcmp(argv[i], "--capacities")) {
|
|
||||||
do_capacities = 1;
|
|
||||||
|
|
||||||
} else if (!strcmp(argv[i], "--toc")) {
|
} else if (!strcmp(argv[i], "--toc")) {
|
||||||
do_toc = 1;
|
do_toc = 1;
|
||||||
|
|
||||||
@ -593,7 +472,7 @@ int telltoc_setup(int argc, char **argv)
|
|||||||
if (print_help) {
|
if (print_help) {
|
||||||
printf("Usage: %s\n", argv[0]);
|
printf("Usage: %s\n", argv[0]);
|
||||||
printf(" [--drive <address>|<driveno>|\"-\"]\n");
|
printf(" [--drive <address>|<driveno>|\"-\"]\n");
|
||||||
printf(" [--media] [--capacities] [--toc] [--msinfo]\n");
|
printf(" [--media] [--toc] [--msinfo]\n");
|
||||||
printf("Examples\n");
|
printf("Examples\n");
|
||||||
printf("A bus scan (needs rw-permissions to see a drive):\n");
|
printf("A bus scan (needs rw-permissions to see a drive):\n");
|
||||||
printf(" %s --drive -\n",argv[0]);
|
printf(" %s --drive -\n",argv[0]);
|
||||||
@ -628,14 +507,13 @@ int main(int argc, char **argv)
|
|||||||
msinfo_alone = 1;
|
msinfo_alone = 1;
|
||||||
}
|
}
|
||||||
/* Default option is to do everything if possible */
|
/* Default option is to do everything if possible */
|
||||||
if (do_media==0 && do_msinfo==0 && do_capacities==0 && do_toc==0
|
if (do_media==0 && do_msinfo==0 && do_toc==0 && driveno!=-1) {
|
||||||
&& driveno!=-1) {
|
|
||||||
if(print_help)
|
if(print_help)
|
||||||
exit(0);
|
exit(0);
|
||||||
full_default = do_media = do_msinfo = do_capacities= do_toc = 1;
|
full_default = do_media = do_msinfo = do_toc = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Initializing libburnia.pykix.org ...\n");
|
fprintf(stderr, "Initializing libburn.pykix.org ...\n");
|
||||||
if (burn_initialize())
|
if (burn_initialize())
|
||||||
fprintf(stderr, "Done\n");
|
fprintf(stderr, "Done\n");
|
||||||
else {
|
else {
|
||||||
@ -660,14 +538,6 @@ int main(int argc, char **argv)
|
|||||||
if (ret<=0)
|
if (ret<=0)
|
||||||
{ret = 36; goto release_drive; }
|
{ret = 36; goto release_drive; }
|
||||||
}
|
}
|
||||||
if (do_capacities) {
|
|
||||||
ret = telltoc_speedlist(drive_list[driveno].drive);
|
|
||||||
if (ret<=0)
|
|
||||||
{ret = 39; goto release_drive; }
|
|
||||||
ret = telltoc_formatlist(drive_list[driveno].drive);
|
|
||||||
if (ret<=0)
|
|
||||||
{ret = 39; goto release_drive; }
|
|
||||||
}
|
|
||||||
if (do_toc) {
|
if (do_toc) {
|
||||||
ret = telltoc_toc(drive_list[driveno].drive);
|
ret = telltoc_toc(drive_list[driveno].drive);
|
||||||
if (ret<=0)
|
if (ret<=0)
|
||||||
|
Reference in New Issue
Block a user