cd-text.texi: Encorporate Thomas' suggestions, revise sectioning; Start using floats in tables, and small corrections.
2663 lines
95 KiB
Plaintext
Executable File
2663 lines
95 KiB
Plaintext
Executable File
\input texinfo @c -*-texinfo-*-
|
|
@c %**start of header
|
|
@setfilename libcdio.info
|
|
@include version.texi
|
|
@settitle GNU @code{libcdio}: Compact Disc Input, Output, and Control Library
|
|
@c %**end of header
|
|
|
|
@c Karl Berry informs me that this will add straight quotes in
|
|
@c typewriter text.
|
|
@c See the "Inserting Quote Characters" node in the Texinfo manual
|
|
@set txicodequoteundirected
|
|
@set txicodequotebacktick
|
|
|
|
@copying
|
|
This manual documents @code{libcdio}, the GNU CD Input, Output, and Control
|
|
Library.
|
|
|
|
Copyright @copyright{} 2003, 2004, 2005, 2006, 2007, 2008, 2010 Rocky
|
|
Bernstein and Herbert Valerio Riedel.
|
|
|
|
@quotation
|
|
Permission is granted to copy, distribute and/or modify this document
|
|
under the terms of the GNU Free Documentation License, Version 1.2 or
|
|
any later version published by the Free Software Foundation; with no
|
|
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
|
Texts. A copy of the license is included in the section entitled
|
|
``GNU Free Documentation License''.
|
|
@end quotation
|
|
@end copying
|
|
|
|
@paragraphindent 0
|
|
@exampleindent 0
|
|
|
|
@set libcdio @code{libcdio}
|
|
@set program @kbd{libcdio}
|
|
|
|
@c A macro for defining terms variables.
|
|
@macro term{varname}
|
|
@c @cindex{\varname\}
|
|
@emph{\varname\}
|
|
@end macro
|
|
|
|
@dircategory Software libraries
|
|
@direntry
|
|
* libcdio: (libcdio). GNU Compact Disc Input, Output, and Control Library.
|
|
@end direntry
|
|
|
|
@titlepage
|
|
@title GNU @code{libcdio}
|
|
@subtitle GNU Compact Disc Input, Output, and Control Library
|
|
@subtitle for version @value{VERSION}, @value{UPDATED}
|
|
@author Rocky Bernstein et al. (@email{bug-libcdio@@gnu.org})
|
|
@page
|
|
@vskip 0pt plus 1filll
|
|
@insertcopying
|
|
@end titlepage
|
|
|
|
@contents
|
|
|
|
@ifnottex
|
|
@node Top
|
|
@top GNU @value{libcdio}
|
|
|
|
@insertcopying
|
|
|
|
@menu
|
|
* History:: How this came about
|
|
* Previous Work:: The problem and previous work
|
|
* Purpose:: What is in this package (and what's not)
|
|
* CD Formats:: A tour through the CD-specification spectrum
|
|
* CD Image Formats:: A tour through various CD-image formats
|
|
* CD Units:: The units that make up a CD
|
|
* How to use:: Okay enough babble, lemme at the library!
|
|
* Utility Programs:: Diagnostic programs that come with this library
|
|
* CD-ROM Access and Drivers:: CD-ROM access and drivers
|
|
* Internal Program Organization:: Looking under the hood
|
|
|
|
Appendices
|
|
* ISO-9660 Character Sets::
|
|
* Glossary::
|
|
* GNU Free Documentation License::
|
|
|
|
Indices
|
|
* General Index:: Overall index
|
|
@end menu
|
|
@end ifnottex
|
|
|
|
@node History
|
|
@chapter History
|
|
|
|
As a result of the repressive Digital Millennium Copyright Act (DMCA)
|
|
I became aware of Video CD's (VCD's). Video CD's are not subject to
|
|
the DMCA and therefore enjoy the protection afforded by copyright but
|
|
no more. But in order for VCD's to be competitive with DVD's, good
|
|
tools (including GPL tools) are needed for authoring and playing
|
|
them. And so through VCD's I became aware of the excellent Video CD
|
|
tools by Herbert Valerio Riedel which form the @kbd{vcdimager} package.
|
|
|
|
Although vcdimager is great for authoring, examining and extracting
|
|
parts of a Video CD, it is not a VCD player. And when I looked at the
|
|
state of Video CD handling in existing VCD players: @code{xine},
|
|
@code{MPlayer}, and @code{vlc}, I was a bit disappointed. None handled
|
|
playback control, menu selections, or playing still frames and
|
|
segments from track 1.
|
|
|
|
Version 0.7.12 of vcdimager was very impressive, however it lacked
|
|
exportable libraries that could be used in other projects. So with the
|
|
blessing and encouragement of Herbert Valerio Riedel, I took to
|
|
extract and create libraries from this code base. The result was two
|
|
libraries: one to extract information from a VCD which I called
|
|
libvcdinfo, and another to do the reading and control of a VCD. Well,
|
|
actually, at this point I should say that a Video CD is really just
|
|
Video put on a existing well-established Compact Disc or CD format. So
|
|
the library for this is called @value{libcdio} rather than
|
|
@kbd{libvcdio}.
|
|
|
|
While on the topic of the name @value{libcdio}, I should also explain that
|
|
the library really doesn't handle writing or output (the final "o" in
|
|
the name). However it was felt that if I put @code{libcdi} that might be
|
|
confused with a particular CD format called CD-I.
|
|
|
|
Later on, the ISO-9660 filesystem handling component from
|
|
@kbd{vcdimager} was extracted, expanded and made a separate
|
|
library. Next the ability to add MMC commands was added, and then
|
|
CD paranoia support. And from there, the rest is history.
|
|
|
|
@node Previous Work
|
|
@chapter The problem and previous work
|
|
|
|
If around the year 2002 you were to look at the code for a number of
|
|
free software CD or media players that work on several platforms such as
|
|
vlc, MPlayer, xine, or xmms to name but a few, you'd find the code to
|
|
read a CD sprinkled with conditional compilation for this or that
|
|
platform. That is there was @emph{no} OS-independent programmer
|
|
library for CD reading and control even though the technology was over
|
|
10 years old; yet there are media players which strive for OS
|
|
independence.
|
|
|
|
One early CD player, @kbd{xmcd} by Ti Kan, was I think a bit better
|
|
than most in that it tried to @emph{encapsulate} the kinds of CD
|
|
control mechanisms (SCSI, Linux ioctl, Toshiba, etc.) in a "CD Audio
|
|
Device Interface Library" called @code{libdi}. However this library is for
|
|
Audio CD's only and I don't believe this library has been used outside
|
|
of xmcd.
|
|
|
|
Another project, Simple DirectMedia Layer also encapsulates CD
|
|
reading.
|
|
|
|
@quotation
|
|
SDL is a library that allows you portable low-level access to a video
|
|
framebuffer, audio output, mouse, and keyboard. With SDL, it is easy
|
|
to write portable games which run on ...
|
|
@end quotation
|
|
|
|
Many of the media players mentioned above do in fact can make use of
|
|
the SDL library but for @emph{video} output only. Because the encapsulation
|
|
is over @emph{many} kinds of I/O (video, joysticks, mice, as well as CD's),
|
|
I believe that the level of control provided for CD a little bit
|
|
limited. (However to be fair, it may have only been intended for games
|
|
and may be suitable for that). Applications that just want the CD
|
|
reading and control portion I think will find quite a bit overhead.
|
|
|
|
Another related project is J@"org Schilling's SCSI library. You can
|
|
use that to make a non-SCSI CD-ROM act like one that understands SCSI
|
|
MMC commands which is a neat thing to do. However it is a little weird
|
|
to have to install drivers just so you can run a particular user-level
|
|
program. Installing drivers often requires special privileges and
|
|
permissions and it is pervasive on a system. It is a little sad that
|
|
along the way to creating such a SCSI library a library similar to
|
|
@value{libcdio} wasn't created which could be used. Were that the
|
|
case, this library certainly never would have been written.
|
|
|
|
At the OS level there is the ``A Linux CD-ROM Standard'' by David van
|
|
Leeuwen from around 1999. This defines a set of definitions and
|
|
ioctl's that mask hardware differences of various Compact Disc
|
|
hardware. It is a great idea, however this ``standard'' lacked
|
|
adoption on OS's other than GNU/Linux. Or maybe it's the case that the
|
|
standard on other OS's lacked adoption on GNU/Linux. For example on
|
|
FreeBSD there is a ``Common Access Method'' (CAM) used for all SCSI
|
|
access which seems not to be adopted in GNU/Linux.@footnote{And I'm
|
|
thankful for that since, at least for MMC commands, it is
|
|
inordinately complicated and in some places arcane.}
|
|
|
|
Finally at the hardware level where a similar chaos exists, there has
|
|
been an attempt to do something similar with the MMC (multimedia
|
|
commands). This attempts to provide a uniform command set for CD
|
|
devices like PostScript does for printer commands.@footnote{I wrote
|
|
``attempts'' because over time the command set has changed and now
|
|
there are several different commands to do a particular function like
|
|
read a CD table of contents and some hardware understands some of the
|
|
version of the commands set but might not others} In contrast to
|
|
PostScript where there one in theory can write a PostScript program in
|
|
a uniform ASCII representation and send that to a printer, for MMC
|
|
although there are common internal structures defined, there is no
|
|
common syntax for representing the structures or an OS-independent
|
|
library or API for issuing MMC-commands which a programmer would need
|
|
to use. Instead each Operating System has its own interface. For
|
|
example Adaptec's ASPI or Microsoft's DeviceIoControl on Microsoft
|
|
Windows, or IOKit for Apple's OS/X, or FreeBSD's CAM. I've been
|
|
positively awed at how many different variations and differing levels
|
|
of complexity there are for doing basically the same thing. How easy
|
|
it is to issue an MMC command from a program varies from easy to very
|
|
difficult. And mastering the boilerplate code to issue an MMC command
|
|
on one OS really doesn't help much in figuring out how to do it on
|
|
another OS. So in @value{libcdio} we provide a common (and hopefully
|
|
simple) API to issue MMC commands.
|
|
|
|
@node Purpose
|
|
@chapter What is in this package (and what's not)
|
|
|
|
The library, @command{libcdio}, encapsulates CD-ROM reading and
|
|
control. Applications wishing to be oblivious of the OS- and
|
|
device-dependent properties of a CD-ROM can use this library.
|
|
|
|
Also included is a library, @command{libiso9660}, for working with
|
|
ISO-9660 filesystems, @command{libcdio_paranoia}, and
|
|
@command{libcdio_cdda} libraries for applications which want to use
|
|
cdparanoia's error-correction and jitter detection.
|
|
|
|
Some support for disk-image types like cdrdao's TOC, CDRWIN's BIN/CUE
|
|
and Ahead Nero's NRG format is available, so applications that use this
|
|
library also have the ability to read disc images as though they were
|
|
CDs.
|
|
|
|
@command{libcdio} also provides a way to issue SCSI ``MultiMedia
|
|
Commands'' (MMC). MMC is supported by many hardware CD-ROM
|
|
manufacturers; and in some cases where a CD-ROM doesn't understand MMC
|
|
directly, some Operating Systems (such as GNU/Linux, Solaris, or
|
|
FreeBSD or Microsoft Windows ASPI to name a few) provide the MMC
|
|
emulation.@footnote{This concept of software emulation of a common
|
|
hardware command language is common for printers such as using
|
|
ghostscript to private postscript emulation for a non-postscript
|
|
printer.}
|
|
|
|
The first use of the library in this package are the Video CD
|
|
authoring and ripping tools, VCDImager
|
|
(@url{http://vcdimager.org}). See
|
|
@url{http://www.gnu.org/software/libcdio/projects.html} for a list of
|
|
projects using @command{libcdio}.
|
|
|
|
A version of the CD-DA extraction tool cdparanoia
|
|
(@url{http://www.xiph.org/paranoia} and its library which corrects
|
|
for CD-ROM jitter are part of the distribution.
|
|
|
|
Also included in the libcdio package is a utility program
|
|
@command{cd-info} which displays CD information: number of tracks,
|
|
CD-format and if possible basic information about the format. If
|
|
libcddb (@url{http://libcddb.sourceforge.net}) is available, the
|
|
@command{cd-info} program will display CDDB matches on CD-DA
|
|
discs. And if a new enough version of libvcdinfo is available (from
|
|
the vcdimager project), then @command{cd-info} shows basic VCD
|
|
information.
|
|
|
|
Other utility programs in the libcdio package are:
|
|
|
|
@table @code
|
|
|
|
@item @code{cdda-player}
|
|
|
|
shows off @value{libcdio} audio and CD-ROM control commands. It can
|
|
play a track, eject or load media and show the the status of a CD-DA
|
|
that is might be currently played via the audio control commands. It
|
|
can be run in batch mode or has a simple curses-based interface.
|
|
|
|
If libcddb is available or a CD has CD-Text and your CD-ROM drive
|
|
supports CD-Text, track/album information about the CD can be shown.
|
|
|
|
@item @code{cd-drive}
|
|
|
|
shows what drivers are available and some basic properties of
|
|
cd-drives attached to the system. (But media may have to be inserted
|
|
in order to get this info.) lists out drive capabilities
|
|
|
|
@item cd-read
|
|
performs low-level block reading of a CD or CD image,
|
|
|
|
@item @code{iso-info}
|
|
|
|
displays ISO-9660 information from an ISO-9660 image. Below is some
|
|
sample output
|
|
|
|
@smallexample
|
|
iso-info version 0.82 x86_64-unknown-linux-gnu
|
|
Copyright (c) 2003, 2004, 2005, 2007, 2008 R. Bernstein
|
|
This is free software; see the source for copying conditions.
|
|
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
|
|
PARTICULAR PURPOSE.
|
|
__________________________________
|
|
ISO 9660 image: ../test/joliet.iso
|
|
Application: K3B THE CD KREATOR VERSION 0.11.12 (C) 2003 SEBASTIAN TRUEG AND...
|
|
Preparer : K3b - Version 0.11.12
|
|
Publisher : Rocky Bernstein
|
|
System : LINUX
|
|
Volume : K3b data project
|
|
Volume Set :
|
|
__________________________________
|
|
ISO-9660 Information
|
|
/:
|
|
Oct 22 2004 19:44 .
|
|
Oct 22 2004 19:44 ..
|
|
Oct 22 2004 19:44 libcdio
|
|
|
|
/libcdio/:
|
|
Oct 22 2004 19:44 .
|
|
Oct 22 2004 19:44 ..
|
|
Mar 12 2004 02:18 COPYING
|
|
Jun 26 2004 07:01 README
|
|
Aug 12 2004 06:22 README.libcdio
|
|
Oct 22 2004 19:44 test
|
|
|
|
/libcdio/test/:
|
|
Oct 22 2004 19:44 .
|
|
Oct 22 2004 19:44 ..
|
|
Jul 25 2004 06:52 isofs-m1.cue
|
|
@end smallexample
|
|
|
|
@item @code{iso-read}
|
|
|
|
extracts files from an ISO-9660 image.
|
|
|
|
@end table
|
|
|
|
Historically, @code{libcdio} did not support write access to
|
|
drives. In conjunction with additional work in a separate project
|
|
@code{libburn}, Thomas Schmitt has modified @code{libcdio} to enable
|
|
sending SCSI write commands on some of the drivers. This enables other
|
|
programs like @code{libburn} to write to CD's, DVD's and Blu-Ray
|
|
discs.
|
|
|
|
For the OS drivers which are lacking write access, volunteers are
|
|
welcome.
|
|
|
|
@node CD Formats
|
|
@chapter CD Formats
|
|
|
|
Much of what I write in this section can be found elsewhere. See for
|
|
example @url{http://www.pctechguide.com/08cd-rom.htm} or
|
|
@url{http://www.pcguide.com/ref/cd/format.htm}
|
|
|
|
We give just enough background here to cover Compact Discs and Compact
|
|
Disc formats that are handled by this library.
|
|
|
|
The Sony and Philips Corporations invented and Compact Disc (CD) in
|
|
the early 1980s. The specifications for the layout is often referred
|
|
to by the color of the cover on the specification.
|
|
|
|
@menu
|
|
* Red Book:: Red Book (CD-DA) CD Text, CDDB
|
|
* Yellow Book:: Yellow Book (CD-ROM Digital Data)
|
|
* Green Book:: Green Book (CD-i)
|
|
* White Book:: White Book (DV, Video CD)
|
|
@end menu
|
|
|
|
@node Red Book
|
|
@section Red Book (CD-DA)
|
|
@cindex Red Book
|
|
|
|
@menu
|
|
* CD Text:: CD Text and CD+G
|
|
* CDDB:: Internet CD Database (CDDB)
|
|
@end menu
|
|
|
|
The first type of CD that was produced was the Compact Disc Digital
|
|
Audio (CD-DA) or just plain ``audio CD''. The specification, ICE 60908
|
|
(formerly IEC 908) is commonly called the ``Red Book'',
|
|
@cite{@url{http://en.wikipedia.org/wiki/Red_Book_(audio_CD_standard)}}. Music
|
|
CD's are recorded in this format which basically allows for around 74
|
|
minutes of audio per disc and for that information to be split up into
|
|
tracks. Tracks are broken up into "sectors" and each sector contains
|
|
up to 2,352 bytes. To play one 44.1 kHz CD-DA sampled audio second, 75
|
|
sectors are used.
|
|
|
|
The minute/second/frame numbering of sectors or MSF format is based on
|
|
the fact that 75 sectors are used in a second of playing of
|
|
sound. (And for almost every other CD format and application the MSF
|
|
format doesn't make that much sense).
|
|
|
|
In @value{libcdio} when you you want to read an audio sector, you call
|
|
@code{cdio_read_audio_sector()} or @code{cdio_read_audio_sectors()}.
|
|
|
|
@cindex subchannel
|
|
In addition the the audio data ``channel'' a provision for other
|
|
information or @term{subchannel} information) can be stored in a
|
|
sector. Other subchannels include a Media Catalog Number (also
|
|
abbreviated as MCN and sometimes a UPC), or album meta data (also
|
|
called CD-Text). Karioke graphics can also be stored in a format
|
|
called @term{CD+G}.
|
|
|
|
@node CD Text
|
|
@subsection CD Text, CD+G
|
|
@cindex CD Text
|
|
@cindex CD+G
|
|
|
|
CD Text is an extension to the CD-DA standard that adds the ability to
|
|
album and track meta data (titles, artist/performer names, song
|
|
titles) and graphical (e.g. Karaoke) information. For an
|
|
alternative way to get album and track meta-data see @xref{CDDB}.
|
|
|
|
Information is stored in such a way that it doesn't interfere with the
|
|
normal operation of any CD players or CDROM drives. There are two
|
|
different parts of the CD where the data can be stored.
|
|
|
|
The first place the information can be recorded is in the R-W sub
|
|
codes in the lead in area of the CD. This information is stored as a
|
|
single block of data and is the format. The method for reading this
|
|
data from a CDROM drive is covered under the Sony proposal to the MMC
|
|
specification. The format of the data is partially covered in the MMC
|
|
specification.
|
|
|
|
CD Text information is stored in this area. The format that follows
|
|
the Interactive Text Transmission System (ITTS) is the same data
|
|
transmission standard used by such things as Digital Audio
|
|
Broadcasting (DAB), and virtually the same as the data standard for
|
|
the MiniDisc.
|
|
|
|
The second place the information can be recorded is in the R-W sub
|
|
codes in the program area of the CD giving a data capacity of roughly
|
|
31MB. CD+G (CD w/graphics) uses this method.
|
|
|
|
The methods for reading this data from a CD-ROM drive were first
|
|
covered by the programming specs from the individual drive
|
|
manufacturers. In the case of ATAPI drives, the SFF8020 spec covers
|
|
the reading of the RW subcodes. Subsequently it has been encorporated
|
|
into the MMC specifications.
|
|
|
|
Not all drives support reading the RW subcodes from the program
|
|
area. However for those that do, @value{libcdio} provides a way to get
|
|
at this information via @code{cdtext_get()} and its friends.
|
|
|
|
There is a separate document in this distribution describing CD-Text
|
|
information and how it is encoded.
|
|
|
|
@node CDDB
|
|
@subsection Internet CD Database (CDDB)
|
|
@cindex CDDB
|
|
|
|
CDDB is an database on the Internet of of CD album/track, artist, and
|
|
genre information similar to CD Text information. Using track
|
|
information (number of tracks and length of the tracks), devices that
|
|
have access to the Internet can query for meta information and
|
|
contribute information for CD's where there is no existing
|
|
information. When storage is available (such as you'd expect for any
|
|
program using @value{libcdio}, the information is often saved for
|
|
later use when the Internet is not available; people tend request the
|
|
same information since they via programs play the same music.
|
|
|
|
Obtaining CD meta information when none is encoded in an audio CD is
|
|
useful in media players or making ones own compilations from audio
|
|
CDs.
|
|
|
|
There are currently two popular CDDB services on the Internet. The
|
|
original database has been renamed Gracenote and is a profit making
|
|
entity. FreeDB (@url{http://freedb.org} is an open source CD
|
|
information resource that is free for developers and the public to
|
|
use.
|
|
|
|
As there already is an excellent library for handling CDDB libcddb
|
|
(@url{http://libcddb.sourceforge.net} we suggest using that. Our
|
|
utility program @command{cd-info} will make use it if it is available
|
|
and it's what we use in our applications that need it.
|
|
|
|
@node Yellow Book
|
|
@section Yellow Book (CD-ROM Digital Data)
|
|
The CD-ROM specification or the ``Yellow Book'' followed a few years
|
|
later (Standards ISO/IEC 10149), and describes the extension of CD's
|
|
to store computer data, i.e. CD-ROM (Compact Disk Read Only Memory).
|
|
|
|
The specification in the Yellow Book defines two modes: Mode 1 and
|
|
Mode 2.
|
|
|
|
@menu
|
|
* ISO 9660::
|
|
* Mode 1:: Mode 1 Format
|
|
* Mode 2:: Mode 2 Format
|
|
@end menu
|
|
|
|
@node ISO 9660
|
|
@subsection ISO 9660
|
|
@cindex ISO 9660
|
|
|
|
@menu
|
|
* ISO 9660 Level 1::
|
|
* ISO 9660 Level 2::
|
|
* ISO 9660 Level 3::
|
|
* Joliet Extensions::
|
|
* Rock Ridge Extensions::
|
|
@end menu
|
|
|
|
The Yellow Book doesn't specify how data is to be stored on a CD-ROM.
|
|
It was feared that different companies would implement proprietary
|
|
data storage formats using this specification, resulting in
|
|
incompatible data CDs. To prevent this, representatives of major
|
|
manufacturers met at the High Sierra Hotel and Casino in Lake Tahoe,
|
|
NV, in 1985, to define a standard for storing data on CDs. This format
|
|
was nicknamed High Sierra Format. In a slightly modified form it was
|
|
later adopted as ISO the ISO 9660 standard. This standard is further
|
|
broken down into 3 "levels", the higher the level, the more
|
|
permissive.
|
|
|
|
@node ISO 9660 Level 1
|
|
@subsubsection ISO 9660 Level 1
|
|
Level 1 ISO 9660 defines names in the 8+3 convention so familiar to
|
|
MS-DOS: eight characters for the filename, a period, and then three
|
|
characters for the file type, all in upper case. The allowed
|
|
characters are A-Z, 0-9, ".", and "_".Level 1 ISO 9660 requires that
|
|
files occupy a contiguous range of sectors. This allows a file to be
|
|
specified with a start block and a count. The maximum directory depth
|
|
is 8. For a table of the characters, see @xref{ISO-9660 Character
|
|
Sets}.
|
|
|
|
@node ISO 9660 Level 2
|
|
@subsubsection ISO 9660 Level 2
|
|
Level 2 ISO 9660 allows far more flexibility in filenames, but isn't
|
|
usable on some systems, notably MS-DOS.
|
|
|
|
@node ISO 9660 Level 3
|
|
@subsubsection ISO 9660 Level 3
|
|
Level 3 ISO-9660 allows non-contiguous files, useful if the file was
|
|
written in multiple packets with packet-writing software.
|
|
|
|
There have been a number of extensions to the ISO 9660 CD-ROM file
|
|
format. One extension is Microsoft's Joliet specification, designed to
|
|
resolve a number of deficiencies in the original ISO 9660 Level 1 file
|
|
system, and in particular to support the long file names used in
|
|
Windows 95 and subsequent versions of Windows.
|
|
|
|
Another extension is the Rock Ridge Interchange Protocol (RRIP), which
|
|
enables the recording of sufficient information to support POSIX File
|
|
System semantics.
|
|
|
|
@node Joliet Extensions
|
|
@subsubsection Joliet Extensions
|
|
@cindex Joliet extensions
|
|
|
|
Joliet extensions were an upward-compatible extension to the ISO 9660
|
|
specification that removes the limitation initially put in to deal
|
|
with the limited filename conventions found in Microsoft DOS OS. In
|
|
particular, the Joliet specification allows for long filenames and
|
|
allows for UCS-BE (BigEndian Unicode) encoding of filenames which
|
|
include mixed case letter, accented characters spaces and various
|
|
symbols.
|
|
|
|
The way all of this is encoded is by adding a second directory and
|
|
filesystem structure in addition to or in parallels to original ISO
|
|
9600 filesystem. The root node of the ISO 9660 filesystem is found via
|
|
the @term{Primary Volume Descriptor} or @term{PVD}. The root of the
|
|
Joliet-encode filesystem is found in a Supplementary Volume
|
|
Descriptor or @term{SVD} defined in the ISO 9660 specification. The
|
|
SVD structure is almost identical to a PVD with a couple of unused
|
|
fields getting used and with the filename encoding changed to UCS-BE.
|
|
|
|
@node Rock Ridge Extensions
|
|
@subsubsection Rock Ridge Extensions
|
|
@cindex Rock Ridge extensions
|
|
|
|
Using the Joliet Extension one overcome the limitedness of the
|
|
original ISO-9660 naming scheme. But another and probably better
|
|
method is to use the Rock Ridge Extension. Not only can one store a
|
|
filename as one does in a POSIX OS, but the other file attributes,
|
|
such as the various timestamps (creation, modification, access), file
|
|
attributes (user, group, file mode permissions, device type, symbolic
|
|
links) can be stored. This is much as one would do in XA attributes;
|
|
however the two are not completely interchangeable in the information
|
|
they store: XA does @emph{not} address filename limitations, and the
|
|
Rock Ridge extensions don't indicate if a sector is in Mode 1 or Mode
|
|
2 format.
|
|
|
|
The Rock Ridge extension makes use of a hook that was defined as part
|
|
of the ISO 9660 standard.
|
|
|
|
@node Mode 1
|
|
@subsection Mode 1 (2048 data bytes per sector)
|
|
@cindex Mode 1
|
|
Mode 1 is the data storage mode used by to store computer data. There
|
|
are 3 layers of error correction. A Compact Disc using only this format can
|
|
hold at most 650 MB. The data is laid out in basically the same way as
|
|
in and audio CD format, except that the 2,352 bytes of data in each
|
|
block are broken down further. 2,048 of these bytes are for ``real''
|
|
data. The other 304 bytes are used for an additional level of error
|
|
detecting and correcting code. This is necessary because data CDs
|
|
cannot tolerate the loss of a handful of bits now and then, the way
|
|
audio CDs can.
|
|
|
|
In @value{libcdio} when you you want to read a mode1
|
|
sector you call the @code{cdio_read_mode1_sector()} or
|
|
@code{cdio_read_mode1_sectors()}.
|
|
|
|
@node Mode 2
|
|
@subsection Mode 2 (2336 data bytes per sector)
|
|
@cindex Mode 2
|
|
Mode 2 data CDs are the same as mode 1 CDs except that the error
|
|
detecting and correcting codes are omitted. So still there are 2
|
|
layers of error correction. A Compact Disc using only this mode can
|
|
thus hold at most 742 MB. Similar to audio CDs, the mode 2 format
|
|
provides a more flexible vehicle for storing types of data that do not
|
|
require high data integrity: for example, graphics and video can use
|
|
this format. But in contrast to the Red Book standard, different modes
|
|
can be mixed together; this is the basis for the extensions to the
|
|
original data CD standards known as CD-ROM Extended Architecture, or
|
|
CD-ROM XA. CD-ROM XA formats currently in use are CD-I Bridge
|
|
formats, Photo CD and Video CD plus Sony's Playstation.
|
|
|
|
In @value{libcdio} when you you want to read a mode1
|
|
sector you call the @code{cdio_read_mode2_sector()} or
|
|
@code{cdio_read_mode2_sectors()}.
|
|
|
|
@node Green Book
|
|
@section Green Book (CD-i)
|
|
@cindex Green Book
|
|
|
|
This was a CD-ROM format developed by Philips for CD-i (an obsolete
|
|
embedded CD-ROM application allowing limited user user interaction
|
|
with films, games and educational applications). The format is ISO
|
|
9660 compliant and introduced mode 2 form 2 addressing. It also
|
|
contains XA (Extended Architecture) attributes.
|
|
|
|
Although some Green Book discs contain CD-i applications which can
|
|
only be played on a CD-i player, others have films or music
|
|
videos. Video CDs in Green-Book format are labeled "Digital Video on
|
|
CD." The Green Book for video is largely superseded by White book
|
|
CD-ROM which draws on this specification.
|
|
|
|
|
|
@node White Book
|
|
@section White Book (DV, Video CD)
|
|
@cindex Green Book
|
|
|
|
The White Book was released by Sony, Philips, Matsushita, and JVC in
|
|
1993, defines the Video CD specification. The White Book is also known
|
|
as Digital Video (DV).
|
|
|
|
A Video CD contains one data track recorded in CD-ROM XA Mode 2 Form
|
|
2. It is always the first track on the disc (Track 1). The ISO-9660
|
|
file structure and a CD-i application program are recorded in this
|
|
track, as well as the Video CD Information Area which gives general
|
|
information about the Video Compact Disc. After the data track, video
|
|
is written in one or more subsequent tracks within the same
|
|
session. These tracks are also recorded in Mode 2 Form 2.
|
|
|
|
In @value{libcdio} when you you want to read a mode2 format 2 audio
|
|
sector you call the @code{cdio_read_mode2_sector()} or
|
|
@code{cdio_read_mode2_sectors()} setting @code{b_form2} to @code{true}.
|
|
|
|
@node CD Image Formats
|
|
@chapter CD Image Formats
|
|
|
|
@menu
|
|
* CDRDAO TOC Format::
|
|
* CDRWIN BIN/CUE Format::
|
|
* NRG Format::
|
|
@end menu
|
|
|
|
In both the @command{cdrdao} and bin/cue formats there is one meta-file with
|
|
extensions @code{.toc} or @code{.cue} respectively and one or more
|
|
files (often with the extension @code{.bin}) which contains the
|
|
content of tracks. The format of the track data is often
|
|
interchangeable between the two formats. For example, in
|
|
@value{libcdio}'s regression tests we make use of this to reduce the
|
|
size of the test data and just provide alternate meta-data files
|
|
(@code{.toc} or @code{.cue}).
|
|
|
|
In contrast to the first two formats, the NRG format consists of a
|
|
single file. This has the advantage of being a self-contained
|
|
unit: in the other two formats it is possible for the meta file to
|
|
refer to a file that can't be found. A disadvantage of the NRG format
|
|
is that the meta data can't be easily viewed or modified say in a text
|
|
file as it can be with the first two formats. In conjunction with this
|
|
disadvantage is another disadvantage that the format is not
|
|
documented, so how @value{libcdio} interprets an NRG image is based on
|
|
inference. It is recommended that one of the other forms be used
|
|
instead of NRG where possible.
|
|
|
|
@node CDRDAO TOC Format
|
|
@section CDRDAO TOC Format
|
|
|
|
This is @command{cdrdao}'s CD-image description format. Since this
|
|
program is GPL and everything about it is in the open, it is the
|
|
preferred format to use. (Alas, at present it isn't as well supported
|
|
in @value{libcdio} as the BIN/CUE format.)
|
|
|
|
The @emph{toc}-file describes what data is written to the media in the
|
|
@acronym{CD-ROM}; it allows control over track/index positions,
|
|
pre-gaps and sub-channel information. It is a text file, so a text
|
|
editor can be used to create, view or modify it.
|
|
|
|
The @cite{cdrdao(1) manual page}, contains more information about this
|
|
format.
|
|
|
|
@subsection CDRDAO Grammar
|
|
|
|
Below are the lexical tokens and grammar for a cdrdao TOC. It was
|
|
taken from the cdrdao's pacct grammar; the token and nonterminal names
|
|
are the same.
|
|
|
|
@example
|
|
#lexclass START
|
|
#token Eof "@@"
|
|
#token "[\t\r\ ]+"
|
|
#token Comment "//~[\n@@]*"
|
|
#token "\n"
|
|
#token BeginString "\""
|
|
#token Integer "[0-9]+"
|
|
#tokclass AudioFile @{ "AUDIOFILE" "FILE" @}
|
|
|
|
#lexclass STRING
|
|
#token EndString "\""
|
|
#token StringQuote "\\\""
|
|
#token StringOctal "\\[0-9][0-9][0-9]"
|
|
#token String "\\"
|
|
#token String "[ ]+"
|
|
#token String "~[\\\n\"\t ]*"
|
|
@end example
|
|
|
|
@example
|
|
|
|
<toc> ::= ( "CATALOG" <string> | <tocType> )* @{ <cdTextGlobal> @}
|
|
( <track> )+ Eof
|
|
|
|
<track> ::= "TRACK" <trackMode>
|
|
@{ <subChannelMode> @}
|
|
( "ISRC" <string> | @{ "NO" @} "COPY" | @{ "NO" @} "PRE_EMPHASIS"
|
|
| "TWO_CHANNEL_AUDIO" | "FOUR_CHANNEL_AUDIO" )*
|
|
@{ <cdTextTrack> @}
|
|
@{ "PREGAP" <msf> @}
|
|
( <subTrack> | "START" @{ msf @} | "END" @{ msf @} )+
|
|
( "INDEX" <msf> )*
|
|
|
|
<subTrack> ::=
|
|
AudioFile <string> @{ "SWAP" @} @{ "#" <sLong> @} <samples>
|
|
| "DATAFILE" <string> @{ "#" <sLong> @{ <dataLength> @} @}
|
|
| "FIFO" <string> <dataLength>
|
|
| "SILENCE" <samples>
|
|
| "ZERO" @{ dataMode @} @{ <subChannelMode> @} <dataLength>
|
|
|
|
|
|
<string> ::= BeginString ( String | StringQuote | StringOctal )+
|
|
EndString
|
|
|
|
<stringEmpty> ::= BeginString ( String | StringQuote | StringOctal )*
|
|
EndString
|
|
|
|
<uLong> ::= Integer
|
|
|
|
<sLong> ::= Integer
|
|
|
|
<msf> ::= Integer ":" Integer ":" Integer
|
|
|
|
<samples> ::= <msf> | <uLong>
|
|
|
|
<dataLength> ::= <msf> | <uLong>
|
|
|
|
<dataMode> ::= "AUDIO" | "MODE0" | "MODE1" | "MODE1_RAW" | "MODE2"
|
|
| "MODE2_RAW" | "MODE2_FORM1" | "MODE2_FORM2" | "MODE2_FORM_MIX"
|
|
|
|
<trackMode> ::= "AUDIO" | "MODE1" | "MODE1_RAW" | "MODE2"
|
|
| "MODE2_RAW" | "MODE2_FORM1" | "MODE2_FORM2" | "MODE2_FORM_MIX"
|
|
|
|
<subChannelMode> ::= "RW" | "RW_RAW"
|
|
|
|
<tocType> ::= "CD_DA" | "CD_ROM" | "CD_ROM_XA" | "CD_I"
|
|
|
|
<packType> ::= "TITLE" | "PERFORMER" | "SONGWRITER" | "COMPOSER" | "ARRANGER"
|
|
| "MESSAGE" | "DISC_ID" | "GENRE" | "TOC_INFO1" | "TOC_INFO2"
|
|
| "RESERVED1" | "RESERVED2" | "RESERVED3" | "RESERVED4" | "UPC_EAN" |
|
|
"ISRC" | "SIZE_INFO"
|
|
|
|
<binaryData> ::= "@{"
|
|
@{ Integer ( "," Integer )* @}
|
|
"@}"
|
|
|
|
<cdTextItem> ::= <packType> ( <stringEmpty> | <binaryData> )
|
|
|
|
<cdTextBlock> ::= "LANGUAGE" Integer "@{" ( <cdTextItem> )* "@}"
|
|
|
|
<cdTextLanguageMap> ::=
|
|
"LANGUAGE_MAP" "@{"
|
|
( Integer ":" ( Integer | "EN" ) )+
|
|
"@}"
|
|
|
|
<cdTextTrack> ::= "CD_TEXT" "@{" ( <cdTextBlock> )* "@}"
|
|
|
|
<cdTextGlobal> ::= "CD_TEXT" "@{" @{ <cdTextLanguageMap> @} ( <cdTextBlock> )* "@}"
|
|
@end example
|
|
|
|
|
|
|
|
@node CDRWIN BIN/CUE Format
|
|
@section CDRWIN BIN/CUE Format
|
|
@cindex BIN/CUE, CD Image Format
|
|
|
|
The format referred to as @emph{CDRWIN BIN/CUE Format} in this manual
|
|
is a popular CD image format used in the @acronym{PC} world. Not
|
|
unlike @command{cdrdao}'s TOC file, the @emph{cue} file describes the
|
|
track layout, i.e. how the sectors are to be placed on the CD
|
|
media. The @emph{cue} file usually contains a reference to a file
|
|
traditionally having the @file{.bin} extension in its filename, the
|
|
@emph{bin} file. This @emph{bin} file contains the sector data payload
|
|
which is to be written to the CD medium according to the description
|
|
in the @emph{cue} file.
|
|
|
|
The following is an attempt to describe the subset of the @file{.cue}
|
|
file syntax used in @value{libcdio} and vcdimager in an EBNF-like
|
|
notation:
|
|
|
|
@subsection BIN/CUE Grammar
|
|
|
|
@example
|
|
@cartouche
|
|
<cue-document> ::= +( <file-line> +<track-expr> )
|
|
|
|
<digit> ::= "0" | "1" ... "8" | "9"
|
|
<number> ::= +<digit>
|
|
<msf> ::= <digit><digit> ":" <digit><digit> ":" <digit><digit>
|
|
|
|
<file-line> ::= "FILE" <pathname-expr> <file-type> <EOL>
|
|
|
|
<pathname-expr> ::= [ "\"" ] <pathname-str-without-spaces> [ "\"" ]
|
|
| "\"" <pathname-str> "\""
|
|
|
|
<file-type> ::= "BINARY"
|
|
|
|
<track-expr> ::= <track-line> [ <flag-line> ]
|
|
[ <pregap-line> ] *<index-line> [ <postgap-line> ]
|
|
|
|
<flag-line> ::= "FLAGS" *<flag-type> <EOL>
|
|
<flag-type> ::= "DCP"
|
|
|
|
<track-line> ::= "TRACK" <number> <track-type> <EOL>
|
|
|
|
<pregap-line> ::= "PREGAP" <msf> <EOL>
|
|
|
|
<index-line> ::= "INDEX" <number> <msf> <EOL>
|
|
|
|
<postgap-line> ::= "POSTGAP" <msf> <EOL>
|
|
|
|
<track-type> ::= "AUDIO" | "MODE1/2048" | "MODE1/2352"
|
|
| "MODE2/2336" | "MODE2/2352"
|
|
|
|
<comment-line> ::= "REM" *<char> <EOL>
|
|
@end cartouche
|
|
@end example
|
|
|
|
@node NRG Format
|
|
@section NRG Format
|
|
@cindex Nero NRG, CD-Image format
|
|
|
|
The format referred to as @emph{NRG Format} in this manual is another
|
|
popular CD image format. It is available only on Nero software
|
|
on a Microsoft Windows Operating System. It is proprietary and not
|
|
generally published, so the information we have comes from guessing
|
|
based on sample CD images. So support for this is incomplete and using
|
|
this format is not recommended.
|
|
|
|
Unlike @command{cdrdao}'s TOC file the BIN/CUE format everything is
|
|
contained in one file. that one can edit Meta information such as the
|
|
number of tracks and track format is contained at the end of the
|
|
file. This information is not intended to be edited through a text
|
|
editor.
|
|
|
|
@node CD Units
|
|
@chapter The units that make up a CD
|
|
|
|
@menu
|
|
* Tracks:: Tracks
|
|
* Sectors:: Block addressing (MSF, LSN, LBA)
|
|
* Pre-gaps:: Track pre-gaps
|
|
@end menu
|
|
|
|
@node Tracks
|
|
@section tracks --- disc subdivisions
|
|
@cindex track
|
|
@cindex gaps
|
|
|
|
In this section we describe CD properties and terms that we make use
|
|
of in @value{libcdio}.
|
|
|
|
A CD is formatted into a number of @term{tracks}, and a CD can hold at
|
|
most 99 such tracks. This is defined by @code{CDIO_CD_MAX_TRACKS} in
|
|
@file{cdio/sector.h}. Between some tracks CD specifications require a
|
|
``2 second'' in gap (called a @term{lead-in gap}. This is unused space
|
|
with no ``data'' similar to the space between tracks on an old
|
|
phonograph. The word ``second'' here really refers to a measure of
|
|
space and not really necessarily an amount of time. However in the
|
|
special case that the CD encodes an audio CD or CD-DA, the amount of
|
|
time to play a gap of this size will take 2 seconds.
|
|
|
|
@cindex lead out
|
|
The beginning (or inner edge) of the CD is supposed to have a ``2
|
|
second'' lead-in gap and there is supposed to be another ``2 second''
|
|
@term{lead-out} gap at the end (or outer edge) of the CD.
|
|
|
|
People have discovered that they can put useful data in the @term{lead-in}
|
|
and @term{lead-out} gaps, and their equipment can read this, violating
|
|
the standards but allowing a CD to store more data.
|
|
|
|
In order to determine the number of tracks on a CD and where they
|
|
start, commands are used to get this table-of-contents or @term{TOC}
|
|
information. Asking about the start of the @term{lead-out track}
|
|
gives the amount of data stored on the Compact Disk. To make it easy
|
|
to specify this leadout track, special constant 0xAA (decimal 170) is
|
|
used to indicate it. This is safe since this is higher than the
|
|
largest legal track position. In @value{libcdio},
|
|
@code{CDIO_CDROM_LEADOUT_TRACK} is defined to be this special value.
|
|
|
|
@node Sectors
|
|
@section block addressing (MSF, LSN, LBA)
|
|
@cindex MSF
|
|
@cindex LSN
|
|
@cindex LBA
|
|
@cindex sectors
|
|
@cindex frames
|
|
|
|
A track is broken up into a number of 2352-byte @emph{blocks} which we
|
|
sometimes call @emph{sectors} or @emph{frames}. Whereas tracks may
|
|
have a gap between them, a block or sector does not. (In
|
|
@value{libcdio} the block size constant is defined using
|
|
@code{CDIO_CD_FRAMESIZE_RAW}).
|
|
|
|
A Compact Disc has a limit on the number of blocks or sectors. This
|
|
values is defined by constant @code{CDIO_CD_MAX_LSN} in
|
|
@file{cdio/sector.h}.
|
|
|
|
One can addressing a block in one of three formats. The oldest format
|
|
is by it's minute/second/frame number, also referred to as @term{MSF}
|
|
and written in time-like format MM:SS:FF (e.g. 30:01:40). It is best
|
|
suited in audio (Red Book) applications. In @value{libcdio}, the type
|
|
@code{msf_t} can be used to declare variables to hold such
|
|
values. Minute, second and frame values are one byte @emph{and stored
|
|
BCD notation}.@footnote{Perhaps this is a @value{libcdio} design
|
|
flaw. It was originally done I guess because it was convenient for
|
|
VCDs.} There are @value{libcdio} conversion routines
|
|
@code{cdio_from_bcd8()} and @code{cdio_to_bcd8()} to convert the
|
|
minute, second, and frame values into or out of integers. If you want
|
|
to print a field in a BCD-encoded MSF, one can use the format
|
|
specifier @code{%x} @emph{(not @code{%d})} and things will come out
|
|
right.
|
|
|
|
In the MSF notation, there are 75 ``frames'' in a ``second,'' and the
|
|
familiar (if awkward) 60 seconds in a minute. @emph{Frame} here is
|
|
what we called a @emph{block} above. The CD specification defines
|
|
``frame'' to be @emph{another} unit which makes up a block. Very
|
|
confusing. A frame is also sometimes called a sector, analogous to
|
|
hard-disk terminology.
|
|
|
|
Even more confusing is using this time-like notation for an address or
|
|
for a length. Too often people confuse the MSF notation this with an
|
|
amount of time. A ``second'' (or @code{CDIO_CD_FRAMES_PER_SEC} blocks)
|
|
in this notation is only a second of playing time for something
|
|
encoded as CD-DA. It does @emph{not} necessarily represent the amount
|
|
time that it will take to play a of Video CD---usually you need more
|
|
blocks than this. Nor does it represent the amount of data used to
|
|
play a second of an MP3---usually you need fewer blocks than this. It
|
|
is also not the amount of time your CD-ROM will take to read a
|
|
``second'' of data off a Compact Disc: for example a 12x CD player
|
|
will read 12x @code{CDIO_CD_FRAMES_PER_SEC}
|
|
@code{CDIO_CD_FRAMSIZE_RAW}-byte blocks in a one second of time.
|
|
|
|
When programming, unless one is working with a CD-DA (and even here,
|
|
only in a time-like fashion), is generally more cumbersome to use an
|
|
MSF rather than a LBA or LSN described below, since subtraction of two
|
|
MSF's has the awkwardness akin to subtraction using Roman Numerals.
|
|
|
|
Probably the simplest way to address a block is to use its @term{LSN}
|
|
or ``logical sector number.'' This just numbers the blocks usually
|
|
from 0 on. @emph{fix me: LSNs can be negative up to the pregap size?}
|
|
The Lead-in and Lead-out gaps described above have LSNs just like any
|
|
other space on a CD. The last unit of address is a @term{LBA}. It is
|
|
the same as a LSN but the 150 blocks associated with the initial
|
|
lead-in is are not counted. So to convert a LBA into an LSN you just
|
|
add 150. Why the distinction between LBA and LSN? I don't know,
|
|
perhaps this has something to do with ``multisession'' CDs.
|
|
|
|
@node Pre-gaps
|
|
@section track pre-gaps -- @acronym{CD-DA} discs and gaps
|
|
@cindex CD-DA
|
|
@cindex gaps
|
|
@cindex lead in
|
|
@cindex lead out
|
|
@cindex pre-gap
|
|
@cindex Q sub-channel
|
|
|
|
Gaps are possibly one of the least understood topics in audio discs.
|
|
In the case of @acronym{CD-DA} discs, standards require a silent 2
|
|
second gap before the first audio track and after the last audio track
|
|
(in each session.) These are respectively referred to as
|
|
@term{lead-in} and @term{lead-out} gaps. No other gaps are required.
|
|
It is important not to confuse the required @term{lead-in} and
|
|
@term{lead-out} gaps with the optional track @term{pre-gap}s. Track
|
|
@term{pre-gap}s are the gaps that may occur between audio tracks.
|
|
Typically, track @term{pre-gap}s are filled with silence so that the
|
|
listener knows that one song has ended, and the next will soon begin.
|
|
However, track @term{pre-gap}s do not have to contain silence. One
|
|
exception is an audio disc of a live performance. Because the
|
|
performer may seamlessly move from one piece of the performance to the
|
|
next, it would be unnatural for the disc to contain silence between
|
|
the two pieces. Instead, the track number updates with no
|
|
interruption in the performance. This allows the listener to either
|
|
hear the entire performance without unnatural interruptions, or to
|
|
conveniently skip to certain pieces of the performance. Finally, some
|
|
@acronym{CD-DA} discs--whose behavior will be described below--lack
|
|
track @term{pre-gap}s altogether although they must still include the
|
|
@term{lead-in} and @term{lead-out} gaps.
|
|
|
|
In order to understand the track @term{pre-gap}s that occur between
|
|
audio tracks, it is necessary to understand how CD players display the
|
|
track number and time. Embedded in each block of audio data is
|
|
non-audio information known as the @term{Q sub-channel}. The
|
|
@term{Q sub-channel} data tells the CD player what track number and time
|
|
it should display while it is playing the block of audio data in which
|
|
the @term{Q sub-channel} data is embedded. Near the end of some
|
|
tracks, the @term{Q sub-channel} may instruct the CD player to update
|
|
the track number to the next track, and display a count down to the
|
|
next track, often starting at -2 seconds and proceeding to zero. This
|
|
is known as an audio track @term{pre-gap}. It may either contain
|
|
silence, or as previously discussed--in the case of live
|
|
performances--it may contain audio. Almost as often as not, there is
|
|
no @term{pre-gap} whatsoever. Regardless, an audio track
|
|
@term{pre-gap} is purely determined by the contents of the
|
|
@term{Q sub-channel}, which is embedded in each audio sector. This has
|
|
some interesting implications for the track forward button.
|
|
|
|
When the track forward button is pressed on a CD player, the CD player
|
|
advances to the next track, skipping that track's @term{pre-gap}.
|
|
This is because the CD player uses the starting address of the track
|
|
from the disc's table of contents (TOC) to determine where to start
|
|
playing a track when either the track forward or track backward
|
|
buttons are pressed. So to hear a @term{pre-gap} for track 4, the
|
|
listener must either listen to track 3 first, or use the track forward
|
|
or backward buttons to go to track 4, then use the seek backward
|
|
button to back up into track 4's @term{pre-gap}, which is really part
|
|
of track 3, at least according to the TOC. Track 1 @term{pre-gap}s
|
|
are especially interesting because some commercial discs have audio
|
|
hidden before the beginning of the first track! The only way to hear
|
|
this hidden audio with a standard player is to use the seek backward
|
|
button as soon as track 1 begins playing!
|
|
|
|
Audio track @term{pre-gap}s may be specified in a couple of different
|
|
ways in the popular cue file format. The first way of specifying a
|
|
@term{pre-gap} is to use the @command{PREGAP} command. This will
|
|
place a @term{pre-gap} containing silence before a track. The second
|
|
way of specifying a @term{pre-gap} is to give a track an
|
|
@command{INDEX 00} as well as the more normal @command{INDEX 01}.
|
|
@command{INDEX 01} will be used to specify the start of the track in
|
|
the disc's TOC, while @command{INDEX 00} will be used to specify the
|
|
start of the track's @term{pre-gap} as recorded in the @term{Q sub-channel}.
|
|
@command{INDEX 00} is ordinarily used for specifying
|
|
track @term{pre-gap}s that contain audio rather than silence. Thus,
|
|
the cue file format may be used to specify track @term{pre-gap}s with
|
|
silence or audio, depending on whether the @command{PREGAP} or
|
|
@command{INDEX 00} commands are specified. If neither type of
|
|
@term{pre-gap} is specified for a track, no @term{pre-gap} is created
|
|
for that track, which merely means the absence of @term{pre-gap}
|
|
information in the @term{Q sub-channel}, and the lack of a short count
|
|
down to the next track.
|
|
|
|
Various @acronym{CD-DA} ripping programs take various approaches to
|
|
track @term{pre-gap}s. Some ripping programs ignore track
|
|
@term{pre-gap}s altogether, relying solely on the disc's TOC to
|
|
determine where tracks begin and end. If a disc is ripped with such a
|
|
program, then re-burned later, the resulting disc will lack track
|
|
@term{pre-gap}s, and thereby lack the playback behavior of counting
|
|
down to the next track. Other ripping programs detect track
|
|
@term{pre-gap}s and record them in the popular cue file format among
|
|
others. Such ripping programs sometimes allow the user to determine
|
|
whether track @term{pre-gap}s will be appended to the prior track or
|
|
pre-pended to the track to which they "belong". Note that if a
|
|
ripping program is ignorant of track @term{pre-gap}s, the track
|
|
@term{pre-gap}s will be appended to the prior track, because that is
|
|
where the disc's TOC puts them. Thus, there are many different ways
|
|
an application may chose to deal with track @term{pre-gap}s.
|
|
Consequently, @kbd{libcdio} does not dictate the policy a ripping
|
|
program should use in dealing with track @term{pre-gap}s. Hence,
|
|
@kbd{libcdio} provides the @code{cdio_get_track_pregap_[lba|lsn]()}
|
|
interfaces to allow the application to deal with track @term{pre-gap}s
|
|
as it sees fit.
|
|
|
|
Note that the @code{cdio_get_track_pregap_[lba|lsn]()} interfaces
|
|
currently only provide information for CDRDAO TOC, CDRWIN BIN/CUE, and
|
|
NRG images. Getting the track @term{pre-gap}s from a CD drive is a
|
|
more complicated problem because not all CD drives support reading the
|
|
@term{Q sub-channel} @emph{directly} at @emph{high} speed, and there is no
|
|
interface to determine whether or not a drive supports this optional
|
|
feature, aside from trying to read the @term{Q sub-channel}, and
|
|
possibly incurring IO errors. However, all drives @emph{do} support reading
|
|
the @term{Q sub-channel} @emph{indirectly} while playing an audio disc by
|
|
asking the drive for the current position. Unfortunately, this occurs
|
|
at normal playback speed, and requires a certain settling time after
|
|
the disc starts playing. Thus, using this @emph{slow} interface
|
|
requires a more sophisticated algorithm, such as binary search or some
|
|
heuristic, like backing up progressively from the end of the prior
|
|
track to look for the next track's @term{pre-gap}. Note that CD
|
|
drives seek @emph{slow}ly, so it is better to simply use a drive that
|
|
can read the @term{Q sub-channel} directly at @emph{high} speed, and
|
|
avoid complicated software solutions. (Not to mention that if the
|
|
user has an older system with an analog audio cable hooked up between
|
|
their soundboard and their drive, and a ripping program uses the
|
|
@emph{slow} interface, the user will hear bits of the audio on the
|
|
disc!) Consequently, because there is no good universal solution to
|
|
the problem of reading the @term{Q sub-channel} from a drive,
|
|
@kbd{libcdio} currently leaves this problem up to the application, a
|
|
problem which is readily approachable through either @kbd{libcdio}'s
|
|
MMC interface or @kbd{libcdio}'s cdda interface. For an example of
|
|
one such application, see @url{https://gna.org/projects/cued/}.
|
|
|
|
The preceding section on track @term{pre-gaps} and @acronym{CD-DA} was
|
|
contributed by Robert William Fuller (@email{hydrologiccycle@@gmail.com}).
|
|
|
|
@node How to use
|
|
@chapter How to use
|
|
|
|
The @value{libcdio} package comes with a number of small example
|
|
programs in the directory @file{example} which demonstrate different
|
|
aspects of the library and show how to use the library. The source
|
|
code to all of the examples here are contained on the package.
|
|
|
|
Other sources for examples would be the larger utility programs
|
|
@command{cd-drive}, @command{cd-info}, @command{cd-read},
|
|
@command{iso-info}, and @command{iso-read} which are all in the
|
|
@file{src} directory of the @value{libcdio} package. See also
|
|
@xref{Utility Programs}.
|
|
|
|
@menu
|
|
* Include problem:: A note about including <cdio/cdio.h>
|
|
* Example 1:: list out tracks and LSNs
|
|
* Example 2:: list drivers available and default CD device
|
|
* Example 3:: figure out what kind of CD (image) we've got
|
|
* Example 4:: use libiso9660 to extract a file from an ISO-9660 image
|
|
* Example 5:: list CD-Text and CD disc mode info
|
|
* Example 6:: run a MMC INQUIRY command
|
|
* Example 7:: using the CD Paranoia library for CD-DA reading
|
|
* All sample programs:: list of all programs in the example directory
|
|
@end menu
|
|
|
|
@node Include problem
|
|
@section A note about including @code{<cdio/cdio.h>}
|
|
|
|
libcdio installs @code{<cdio/cdio_config.h>}. This file contains all of
|
|
the C Preprocessor values from @code{config.h} (created by configure).
|
|
|
|
This header can be used to consult exactly how libcdio was built. Initially
|
|
I had selected ``interesting'' values, but this became too hard to maintain.
|
|
|
|
One set of values that libdio needs internally is the whether the CPU
|
|
that was used to compile libcdio is BigEndian or not; it can get this
|
|
from libcdio's @code{config.h} which is not installed and preferred or
|
|
@code{cdio/cdio_config.h}.
|
|
|
|
Some of the libcdio programs like the demo programs include
|
|
@code{config.h} for the generic reasons that the configuration-created
|
|
@code{config.h} file is used: to figure out what headers are available.
|
|
For example, do we have @code{<unistd.h>}?
|
|
|
|
The file @code{config.h} is generated by an autotools-generated
|
|
@code{configure} script. It doesn't check to see if it has been included
|
|
previously.
|
|
|
|
Later, the demo programs include @code{<cdio.h>} to get libcdio headers.
|
|
But because libcdio needs some of the same information like the BigEndian
|
|
value, this creates a duplicate include.
|
|
|
|
The way I get around this in the demo programs is by defining @code{__CDIO_CONFIG_H__} after
|
|
including @code{config.h} as follows:
|
|
|
|
@smallexample
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
# define __CDIO_CONFIG_H__ 1
|
|
#endif
|
|
@end smallexample
|
|
|
|
Applications using libcdio may find it handy to do something like this as well.
|
|
|
|
Defining @code{__CDIO_CONFIG_H__} will make sure @code{config_cdio.h}
|
|
which is internally used, doesn't try to redefine preprocessor symbols.
|
|
|
|
Ok. But now what about the problem that there are common preprocessor
|
|
symbols in @code{config_cdio.h} that an application may want to define in a
|
|
different manner, like @code{PACKAGE_NAME}?
|
|
|
|
For this, there is yet another header, @code{<cdio/cdio_unconfig.h>}.
|
|
This file undefines any symbol that @code{config.h} defines. And now we
|
|
bounce to the problem that there may be symbols that are normally
|
|
defined (@code{HAVE_UNISTD_H}) and you want to keep that way, but others that
|
|
you don't. So here is what I suggest:
|
|
|
|
@smallexample
|
|
// for cdio:
|
|
#include <cdio.h>
|
|
#include <cdio_unconfig.h> # remove *all* symbols libcdio defines
|
|
|
|
// Add back in the ones you want your program
|
|
#include <config.h>
|
|
@end smallexample
|
|
|
|
The solution isn't the most simple or natural, but programming sometimes can
|
|
be difficult. If someone has a better solution, let me know.
|
|
|
|
Between header files @code{cdio_config.h} and @code{cdio_unconfig.h} and
|
|
all the fact that almost all headers@footnote{@code{<cdio_unconfig.h>} is
|
|
one of the few headers that doesn't set a preprocessor symbol: it does
|
|
its thing every time it is @code{#included}} define a symbol to indicate they
|
|
have been included, I think there is enough mechanism to cover most
|
|
situations that may arise.
|
|
|
|
@node Example 1
|
|
@section Example 1: list out tracks and LSNs
|
|
Here we will give an annotated example which can be found in the
|
|
distribution as @file{example/tracks.c}.
|
|
|
|
@smallexample
|
|
1: #include <stdio.h>
|
|
2: #include <sys/types.h>
|
|
3: #include <cdio/cdio.h>
|
|
4: int
|
|
5: main(int argc, const char *argv[])
|
|
6: @{
|
|
7: CdIo_t *p_cdio = cdio_open ("/dev/cdrom", DRIVER_DEVICE);
|
|
8: track_t first_track_num = cdio_get_first_track_num(p_cdio);
|
|
9: track_t i_tracks = cdio_get_num_tracks(p_cdio);
|
|
10: int j, i=first_track_num;
|
|
11:
|
|
12: printf("CD-ROM Track List (%i - %i)\n", first_track_num, i_tracks);
|
|
13
|
|
14: printf(" #: LSN\n");
|
|
15:
|
|
16: for (j = 0; j < i_tracks; i++, j++) @{
|
|
17: lsn_t lsn = cdio_get_track_lsn(p_cdio, i);
|
|
18: if (CDIO_INVALID_LSN != lsn)
|
|
19: printf("%3d: %06d\n", (int) i, lsn);
|
|
20: @}
|
|
21: printf("%3X: %06d leadout\n", CDIO_CDROM_LEADOUT_TRACK,
|
|
22: cdio_get_track_lsn(p_cdio, CDIO_CDROM_LEADOUT_TRACK));
|
|
23: cdio_destroy(p_cdio);
|
|
24: return 0;
|
|
25: @}
|
|
@end smallexample
|
|
|
|
Already from the beginning on line 2 we see something odd. The
|
|
@code{#include <sys/types.h>} is needed because @value{libcdio}
|
|
assumes type definitions exist for @code{uint32_t}, @code{uint16_t}
|
|
and so on. Alternatively you change line 2 to:
|
|
|
|
@smallexample
|
|
#define HAVE_SYS_TYPES_H
|
|
@end smallexample
|
|
|
|
and @code{<cdio/cdio.h>} will insert line 2. If you use GNU autoconf
|
|
to configure your program, add @code{sys/types.h} to
|
|
@code{AC_HAVE_HEADERS} and @emph{it} will arrange for
|
|
@code{HAVE_SYS_TYPES_H} to get defined. If you don't have
|
|
@code{<sys/types.h>} but have some other include that defines these
|
|
types, put that instead of line 2. Or you could roll your own
|
|
typedefs. (Note: In the future, this will probably get ``fixed'' by
|
|
requiring glib.h.)
|
|
|
|
Okay after getting over the hurdle of line 2, the next line pretty
|
|
straightforward: you need to include this to get cdio definitions. One
|
|
of the types that is defined via line 3 is @code{CdIo_t} and a pointer
|
|
that is used pretty much in all operations. Line 6 initializes the
|
|
variable @code{cdio} which we will be using in all of the subsequent
|
|
libcdio calls. It does this via a call to @code{cdio_open()}.
|
|
|
|
The second parameter of @code{cdio_open} is DRIVER_UNKNOWN. For any
|
|
given installation a number of Compact Disc device drivers may be
|
|
available. In particular it's not uncommon to have several drivers
|
|
that can read CD disk-image formats as well as a driver that handles
|
|
some CD-ROM piece of hardware. Using DRIVER_UNKNOWN as that second
|
|
parameter we let the library select a driver amongst those that are
|
|
available; generally the first hardware driver that is available is
|
|
the one selected.
|
|
|
|
If there is no CD in any of the CD-ROM drives or one does not have
|
|
access to the CD-ROM, it is possible that @value{libcdio} will find a
|
|
CD image in the directory you run this program and will pick a
|
|
suitable CD-image driver. If this is not what you want, but always
|
|
want some sort of CD-ROM driver (or failure if none), then use
|
|
DRIVER_DEVICE instead of DRIVER_UNKNOWN.
|
|
|
|
Note that in contrast to what is typically done using ioctls to read a
|
|
CD, you don't issue any sort of CD-ROM read TOC command---that is all
|
|
done by the driver. Of course, the information that you get from
|
|
reading the TOC is often desired: many tracks are on the CD, or what
|
|
number the first one is called. This is done through calls on lines 8
|
|
and 9.
|
|
|
|
For each track, we call a cdio routine to get the logical sector
|
|
number, @code{cdio_get_track_lsn()} on line 17 and print the track
|
|
number and LSN value. Finally we print out the ``lead-out track''
|
|
information and we finally call @code{cdio_destroy()} in line 23 to
|
|
indicate we're done with the CD.
|
|
|
|
@node Example 2
|
|
@section Example 2: list drivers available and default CD device
|
|
|
|
One thing that's a bit hockey in Example 1 is hard-coding the name of
|
|
the device used: @code{/dev/cdrom}. Although often this is the name of
|
|
a CD-ROM device on GNU/Linux and possibly some other Unix derivatives,
|
|
there are many OSs for which use a different device name.
|
|
|
|
In the next example, we'll let the driver give us the name of the CD-ROM
|
|
device that is right for it.
|
|
|
|
@smallexample
|
|
1: #include <stdio.h>
|
|
2: #include <sys/types.h>
|
|
3: #include <cdio/cdio.h>
|
|
4: int
|
|
5: main(int argc, const char *argv[])
|
|
6: @{
|
|
7: CdIo_t *p_cdio = cdio_open (NULL, DRIVER_DEVICE);
|
|
8: const driver_id_t *driver_id_p;
|
|
9:
|
|
10: if (NULL != p_cdio) @{
|
|
11: printf("The driver selected is %s\n", cdio_get_driver_name(p_cdio));
|
|
12: printf("The default device for this driver is %s\n\n",
|
|
13: cdio_get_default_device(p_cdio));
|
|
14: cdio_destroy(p_cdio);
|
|
15: @} else @{
|
|
16: printf("Problem in trying to find a driver.\n\n");
|
|
17: @}
|
|
18:
|
|
19: for (driver_id_p=cdio_drivers; *driver_id_p!=DRIVER_UNKNOWN; driver_id_p++)
|
|
20: if (cdio_have_driver(*driver_id_p))
|
|
21: printf("We have: %s\n", cdio_driver_describe(*driver_id_p));
|
|
22: else
|
|
23: printf("We don't have: %s\n", cdio_driver_describe(*driver_id_p));
|
|
24: return 0;
|
|
25: @}
|
|
@end smallexample
|
|
|
|
|
|
@node Example 3
|
|
@section Example 3: figure out what kind of CD (image) we've got
|
|
|
|
In this example is a somewhat simplified program to show the use of
|
|
@command{cdio_guess_cd_type()} to figure out the kind of CD image
|
|
we've got. This can be found in the distribution as @file{example/sample3.c}.
|
|
|
|
@smallexample
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <cdio/cdio.h>
|
|
#include <cdio/cd_types.h>
|
|
|
|
static void
|
|
print_analysis(cdio_iso_analysis_t cdio_iso_analysis,
|
|
cdio_fs_anal_t fs, int first_data, unsigned int num_audio,
|
|
track_t i_tracks, track_t first_track_num, CdIo_t *cdio)
|
|
@{
|
|
switch(CDIO_FSTYPE(fs)) @{
|
|
case CDIO_FS_AUDIO:
|
|
break;
|
|
case CDIO_FS_ISO_9660:
|
|
printf("CD-ROM with ISO 9660 filesystem");
|
|
if (fs & CDIO_FS_ANAL_JOLIET) @{
|
|
printf(" and joliet extension level %d", cdio_iso_analysis.joliet_level);
|
|
@}
|
|
if (fs & CDIO_FS_ANAL_ROCKRIDGE)
|
|
printf(" and rockridge extensions");
|
|
printf("\n");
|
|
break;
|
|
case CDIO_FS_ISO_9660_INTERACTIVE:
|
|
printf("CD-ROM with CD-RTOS and ISO 9660 filesystem\n");
|
|
break;
|
|
case CDIO_FS_HIGH_SIERRA:
|
|
printf("CD-ROM with High Sierra filesystem\n");
|
|
break;
|
|
case CDIO_FS_INTERACTIVE:
|
|
printf("CD-Interactive%s\n", num_audio > 0 ? "/Ready" : "");
|
|
break;
|
|
case CDIO_FS_HFS:
|
|
printf("CD-ROM with Macintosh HFS\n");
|
|
break;
|
|
case CDIO_FS_ISO_HFS:
|
|
printf("CD-ROM with both Macintosh HFS and ISO 9660 filesystem\n");
|
|
break;
|
|
case CDIO_FS_UFS:
|
|
printf("CD-ROM with Unix UFS\n");
|
|
break;
|
|
case CDIO_FS_EXT2:
|
|
printf("CD-ROM with Linux second extended filesystem\n");
|
|
break;
|
|
case CDIO_FS_3DO:
|
|
printf("CD-ROM with Panasonic 3DO filesystem\n");
|
|
break;
|
|
case CDIO_FS_UNKNOWN:
|
|
printf("CD-ROM with unknown filesystem\n");
|
|
break;
|
|
@}
|
|
switch(CDIO_FSTYPE(fs)) @{
|
|
case CDIO_FS_ISO_9660:
|
|
case CDIO_FS_ISO_9660_INTERACTIVE:
|
|
case CDIO_FS_ISO_HFS:
|
|
printf("ISO 9660: %i blocks, label `%.32s'\n",
|
|
cdio_iso_analysis.isofs_size, cdio_iso_analysis.iso_label);
|
|
break;
|
|
@}
|
|
if (first_data == 1 && num_audio > 0)
|
|
printf("mixed mode CD ");
|
|
if (fs & CDIO_FS_ANAL_XA)
|
|
printf("XA sectors ");
|
|
if (fs & CDIO_FS_ANAL_MULTISESSION)
|
|
printf("Multisession");
|
|
if (fs & CDIO_FS_ANAL_HIDDEN_TRACK)
|
|
printf("Hidden Track ");
|
|
if (fs & CDIO_FS_ANAL_PHOTO_CD)
|
|
printf("%sPhoto CD ",
|
|
num_audio > 0 ? " Portfolio " : "");
|
|
if (fs & CDIO_FS_ANAL_CDTV)
|
|
printf("Commodore CDTV ");
|
|
if (first_data > 1)
|
|
printf("CD-Plus/Extra ");
|
|
if (fs & CDIO_FS_ANAL_BOOTABLE)
|
|
printf("bootable CD ");
|
|
if (fs & CDIO_FS_ANAL_VIDEOCD && num_audio == 0) @{
|
|
printf("Video CD ");
|
|
@}
|
|
if (fs & CDIO_FS_ANAL_SVCD)
|
|
printf("Super Video CD (SVCD) or Chaoji Video CD (CVD)");
|
|
if (fs & CDIO_FS_ANAL_CVD)
|
|
printf("Chaoji Video CD (CVD)");
|
|
printf("\n");
|
|
@}
|
|
|
|
int
|
|
main(int argc, const char *argv[])
|
|
@{
|
|
CdIo_t *p_cdio = cdio_open (NULL, DRIVER_UNKNOWN);
|
|
cdio_fs_anal_t fs=0;
|
|
|
|
track_t i_tracks;
|
|
track_t first_track_num;
|
|
lsn_t start_track; /* first sector of track */
|
|
lsn_t data_start =0; /* start of data area */
|
|
|
|
int first_data = -1; /* # of first data track */
|
|
int first_audio = -1; /* # of first audio track */
|
|
unsigned int num_data = 0; /* # of data tracks */
|
|
unsigned int num_audio = 0; /* # of audio tracks */
|
|
unsigned int i;
|
|
|
|
if (NULL == p_cdio) @{
|
|
printf("Problem in trying to find a driver.\n\n");
|
|
return 1;
|
|
@}
|
|
|
|
first_track_num = cdio_get_first_track_num(p_cdio);
|
|
i_tracks = cdio_get_num_tracks(p_cdio);
|
|
|
|
/* Count the number of data and audio tracks. */
|
|
for (i = first_track_num; i <= i_tracks; i++) @{
|
|
if (TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i)) @{
|
|
num_audio++;
|
|
if (-1 == first_audio) first_audio = i;
|
|
@} else @{
|
|
num_data++;
|
|
if (-1 == first_data) first_data = i;
|
|
@}
|
|
@}
|
|
|
|
/* try to find out what sort of CD we have */
|
|
if (0 == num_data) @{
|
|
printf("Audio CD\n");
|
|
@} else @{
|
|
/* we have data track(s) */
|
|
int j;
|
|
cdio_iso_analysis_t cdio_iso_analysis;
|
|
|
|
memset(&cdio_iso_analysis, 0, sizeof(cdio_iso_analysis));
|
|
|
|
for (j = 2, i = first_data; i <= i_tracks; i++) @{
|
|
lsn_t lsn;
|
|
track_format_t track_format = cdio_get_track_format(p_cdio, i);
|
|
|
|
lsn = cdio_get_track_lsn(p_cdio, i);
|
|
|
|
switch ( track_format ) @{
|
|
case TRACK_FORMAT_AUDIO:
|
|
case TRACK_FORMAT_ERROR:
|
|
break;
|
|
case TRACK_FORMAT_CDI:
|
|
case TRACK_FORMAT_XA:
|
|
case TRACK_FORMAT_DATA:
|
|
case TRACK_FORMAT_PSX:
|
|
;
|
|
@}
|
|
|
|
start_track = (i == 1) ? 0 : lsn;
|
|
|
|
/* save the start of the data area */
|
|
if (i == first_data)
|
|
data_start = start_track;
|
|
|
|
/* skip tracks which belong to the current walked session */
|
|
if (start_track < data_start + cdio_iso_analysis.isofs_size)
|
|
continue;
|
|
|
|
fs = cdio_guess_cd_type(p_cdio, start_track, i, &cdio_iso_analysis);
|
|
|
|
print_analysis(cdio_iso_analysis, fs, first_data, num_audio,
|
|
i_tracks, first_track_num, p_cdio);
|
|
|
|
if ( !(CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660 ||
|
|
CDIO_FSTYPE(fs) == CDIO_FS_ISO_HFS ||
|
|
CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660_INTERACTIVE) )
|
|
/* no method for non-ISO9660 multisessions */
|
|
break;
|
|
@}
|
|
@}
|
|
cdio_destroy(p_cdio);
|
|
return 0;
|
|
@}
|
|
@end smallexample
|
|
|
|
@node Example 4
|
|
@section Example 4: use libiso9660 to extract a file from an ISO-9660 image
|
|
|
|
Next a program to show using @command{libiso9660} to extract a file
|
|
from an ISO-9660 image. This can be found in the distribution as
|
|
@file{example/isofile.c}. A more complete and expanded version of this
|
|
is @command{iso-read}, part of this distribution.
|
|
|
|
@smallexample
|
|
/* This is the ISO 9660 image. */
|
|
#define ISO9660_IMAGE_PATH "../"
|
|
#define ISO9660_IMAGE ISO9660_IMAGE_PATH "test/copying.iso"
|
|
|
|
#define LOCAL_FILENAME "copying"
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <cdio/cdio.h>
|
|
#include <cdio/iso9660.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#ifdef HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#endif
|
|
#ifdef HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
#include <sys/types.h>
|
|
#endif
|
|
|
|
#define my_exit(rc) \
|
|
fclose (p_outfd); \
|
|
free(p_statbuf); \
|
|
iso9660_close(p_iso); \
|
|
return rc; \
|
|
|
|
int
|
|
main(int argc, const char *argv[])
|
|
@{
|
|
iso9660_stat_t *p_statbuf;
|
|
FILE *p_outfd;
|
|
int i;
|
|
|
|
iso9660_t *p_iso = iso9660_open (ISO9660_IMAGE);
|
|
|
|
if (NULL == p_iso) @{
|
|
fprintf(stderr, "Sorry, couldn't open ISO 9660 image %s\n", ISO9660_IMAGE);
|
|
return 1;
|
|
@}
|
|
|
|
p_statbuf = iso9660_ifs_stat_translate (p_iso, LOCAL_FILENAME);
|
|
|
|
if (NULL == p_statbuf)
|
|
@{
|
|
fprintf(stderr,
|
|
"Could not get ISO-9660 file information for file %s\n",
|
|
LOCAL_FILENAME);
|
|
iso9660_close(p_iso);
|
|
return 2;
|
|
@}
|
|
|
|
if (!(p_outfd = fopen (LOCAL_FILENAME, "wb")))
|
|
@{
|
|
perror ("fopen()");
|
|
free(p_statbuf);
|
|
iso9660_close(p_iso);
|
|
return 3;
|
|
@}
|
|
|
|
/* Copy the blocks from the ISO-9660 filesystem to the local filesystem. */
|
|
for (i = 0; i < p_statbuf->size; i += ISO_BLOCKSIZE)
|
|
@{
|
|
char buf[ISO_BLOCKSIZE];
|
|
|
|
memset (buf, 0, ISO_BLOCKSIZE);
|
|
|
|
if ( ISO_BLOCKSIZE != iso9660_iso_seek_read (p_iso, buf, p_statbuf->lsn
|
|
+ (i / ISO_BLOCKSIZE),
|
|
1) )
|
|
@{
|
|
fprintf(stderr, "Error reading ISO 9660 file at lsn %lu\n",
|
|
(long unsigned int) p_statbuf->lsn + (i / ISO_BLOCKSIZE));
|
|
my_exit(4);
|
|
@}
|
|
|
|
|
|
fwrite (buf, ISO_BLOCKSIZE, 1, p_outfd);
|
|
|
|
if (ferror (p_outfd))
|
|
@{
|
|
perror ("fwrite()");
|
|
my_exit(5);
|
|
@}
|
|
@}
|
|
|
|
fflush (p_outfd);
|
|
|
|
/* Make sure the file size has the exact same byte size. Without the
|
|
truncate below, the file will a multiple of ISO_BLOCKSIZE.
|
|
*/
|
|
if (ftruncate (fileno (p_outfd), p_statbuf->size))
|
|
perror ("ftruncate()");
|
|
|
|
my_exit(0);
|
|
@}
|
|
@end smallexample
|
|
|
|
@node Example 5
|
|
@section Example 5: list CD-Text and disc mode info
|
|
|
|
Next a program to show using @command{libcdio} to list CD-TEXT data.
|
|
This can be found in the distribution as @file{example/cdtext.c}.
|
|
|
|
@smallexample
|
|
/* Simple program to list CD-Text info of a Compact Disc using libcdio. */
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <cdio/cdio.h>
|
|
#include <cdio/cdtext.h>
|
|
|
|
|
|
static void
|
|
print_cdtext_track_info(CdIo_t *p_cdio, track_t i_track, const char *message) @{
|
|
const cdtext_t *cdtext = cdio_get_cdtext(p_cdio, 0);
|
|
if (NULL != cdtext) @{
|
|
cdtext_field_t i;
|
|
|
|
printf("%s\n", message);
|
|
|
|
for (i=0; i < MAX_CDTEXT_FIELDS; i++) @{
|
|
if (cdtext->field[i]) @{
|
|
printf("\t%s: %s\n", cdtext_field2str(i), cdtext->field[i]);
|
|
@}
|
|
@}
|
|
@}
|
|
|
|
@}
|
|
|
|
static void
|
|
print_disc_info(CdIo_t *p_cdio, track_t i_tracks, track_t i_first_track) @{
|
|
track_t i_last_track = i_first_track+i_tracks;
|
|
discmode_t cd_discmode = cdio_get_discmode(p_cdio);
|
|
|
|
printf("%s\n", discmode2str[cd_discmode]);
|
|
|
|
print_cdtext_track_info(p_cdio, 0, "\nCD-Text for Disc:");
|
|
for ( ; i_first_track < i_last_track; i_first_track++ ) @{
|
|
char psz_msg[50];
|
|
sprintf(msg, "CD-Text for Track %d:", i_first_track);
|
|
print_cdtext_track_info(p_cdio, i_first_track, psz_msg);
|
|
@}
|
|
@}
|
|
|
|
int
|
|
main(int argc, const char *argv[])
|
|
@{
|
|
track_t i_first_track;
|
|
track_t i_tracks;
|
|
CdIo_t *p_cdio;
|
|
cdio = cdio_open (NULL, DRIVER_UNKNOWN);
|
|
i_first_track = cdio_get_first_track_num(p_cdio);
|
|
i_tracks = cdio_get_num_tracks(p_cdio);
|
|
|
|
if (NULL == p_cdio) @{
|
|
printf("Couldn't find CD\n");
|
|
return 1;
|
|
@} else @{
|
|
print_disc_info(p_cdio, i_tracks, i_first_track);
|
|
@}
|
|
|
|
cdio_destroy(p_cdio);
|
|
|
|
return 0;
|
|
@}
|
|
@end smallexample
|
|
|
|
@node Example 6
|
|
@section Example 6: Using MMC to run an @code{INQURY} command
|
|
|
|
Now a program to show issuing a simple MMC command
|
|
(@code{INQUIRY}). This MMC command retrieves the vendor, model and
|
|
firmware revision number of a CD drive. For this command to work,
|
|
usually a CD to be loaded into the drive; odd since the CD itself is
|
|
not used.
|
|
|
|
This can be found in the distribution as @file{example/mmc1.c}.
|
|
|
|
@smallexample
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
# define __CDIO_CONFIG_H__ 1 /* assumes config.h is libcdio's config.h /
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <cdio/cdio.h>
|
|
#include <cdio/scsi_mmc.h>
|
|
#include <string.h>
|
|
|
|
/* Set how long to wait for MMC commands to complete */
|
|
#define DEFAULT_TIMEOUT_MS 10000
|
|
|
|
int
|
|
main(int argc, const char *argv[])
|
|
@{
|
|
CdIo_t *p_cdio;
|
|
|
|
p_cdio = cdio_open (NULL, DRIVER_UNKNOWN);
|
|
|
|
if (NULL == p_cdio) @{
|
|
printf("Couldn't find CD\n");
|
|
return 1;
|
|
@} else @{
|
|
int i_status; /* Result of MMC command */
|
|
char buf[36] = @{ 0, @}; /* Place to hold returned data */
|
|
scsi_mmc_cdb_t cdb = @{@{0, @}@}; /* Command Descriptor Buffer */
|
|
|
|
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_INQUIRY);
|
|
cdb.field[4] = sizeof(buf);
|
|
|
|
i_status = scsi_mmc_run_cmd(p_cdio, DEFAULT_TIMEOUT_MS,
|
|
&cdb, SCSI_MMC_DATA_READ,
|
|
sizeof(buf), &buf);
|
|
if (i_status == 0) @{
|
|
char psz_vendor[CDIO_MMC_HW_VENDOR_LEN+1];
|
|
char psz_model[CDIO_MMC_HW_MODEL_LEN+1];
|
|
char psz_rev[CDIO_MMC_HW_REVISION_LEN+1];
|
|
|
|
memcpy(psz_vendor, buf + 8, sizeof(psz_vendor)-1);
|
|
psz_vendor[sizeof(psz_vendor)-1] = '\0';
|
|
memcpy(psz_model,
|
|
buf + 8 + CDIO_MMC_HW_VENDOR_LEN,
|
|
sizeof(psz_model)-1);
|
|
psz_model[sizeof(psz_model)-1] = '\0';
|
|
memcpy(psz_rev,
|
|
buf + 8 + CDIO_MMC_HW_VENDOR_LEN +CDIO_MMC_HW_MODEL_LEN,
|
|
sizeof(psz_rev)-1);
|
|
psz_rev[sizeof(psz_rev)-1] = '\0';
|
|
|
|
printf("Vendor: %s\nModel: %s\nRevision: %s\n",
|
|
psz_vendor, psz_model, psz_rev);
|
|
@} else @{
|
|
printf("Couldn't get INQUIRY data (vendor, model, and revision\n");
|
|
@}
|
|
@}
|
|
|
|
cdio_destroy(p_cdio);
|
|
|
|
return 0;
|
|
@}
|
|
@end smallexample
|
|
|
|
Note the include of @code{#define} of @code{__CDIO_CONFIG_H__} towards
|
|
the beginning. This is useful if the prior @code{#include} of
|
|
@code{config.h} refers to libcdio's configuration header. It indicates
|
|
that libcdio's configuration settings have been used. Without it, you
|
|
may get messages about C Preprocessor symbols getting redefined in the
|
|
@code{#include} of @code{<cdio.cdio.h>}.
|
|
|
|
@node Example 7
|
|
@section Example 7: Using the CD Paranoia library for CD-DA reading
|
|
|
|
The below program reads CD-DA data. For a more complete program to add
|
|
a WAV header so that the CD can be played from a copy on a hard disk,
|
|
see the corresponding distribution program.
|
|
|
|
This can be found in the distribution as @file{example/paranoia.c}.
|
|
|
|
@smallexample
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
# define __CDIO_CONFIG_H__ 1 /* assumes config.h is libcdio's config.h /
|
|
#endif
|
|
|
|
#include <cdio/cdda.h>
|
|
#include <cdio/cd_types.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
|
|
int
|
|
main(int argc, const char *argv[])
|
|
@{
|
|
cdrom_drive_t *d = NULL; /* Place to store handle given by cd-paranoia. */
|
|
char **ppsz_cd_drives; /* List of all drives with a loaded CDDA in it. */
|
|
|
|
/* See if we can find a device with a loaded CD-DA in it. */
|
|
ppsz_cd_drives = cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
|
|
|
|
if (ppsz_cd_drives) @{
|
|
/* Found such a CD-ROM with a CD-DA loaded. Use the first drive in
|
|
the list. */
|
|
d=cdio_cddap_identify(*ppsz_cd_drives, 1, NULL);
|
|
@} else @{
|
|
printf("Unable find or access a CD-ROM drive with an audio CD in it.\n");
|
|
exit(1);
|
|
@}
|
|
|
|
/* Don't need a list of CD's with CD-DA's any more. */
|
|
cdio_free_device_list(ppsz_cd_drives);
|
|
|
|
/* We'll set for verbose paranoia messages. */
|
|
cdio_cddap_verbose_set(d, CDDA_MESSAGE_PRINTIT, CDDA_MESSAGE_PRINTIT);
|
|
|
|
if ( 0 != cdio_cddap_open(d) ) @{
|
|
printf("Unable to open disc.\n");
|
|
exit(1);
|
|
@}
|
|
|
|
/* Okay now set up to read up to the first 300 frames of the first
|
|
audio track of the Audio CD. */
|
|
@{
|
|
cdrom_paranoia_t *p = cdio_paranoia_init(d);
|
|
lsn_t i_first_lsn = cdio_cddap_disc_firstsector(d);
|
|
|
|
if ( -1 == i_first_lsn ) @{
|
|
printf("Trouble getting starting LSN\n");
|
|
@} else @{
|
|
lsn_t i_cursor;
|
|
track_t i_track = cdio_cddap_sector_gettrack(d, i_first_lsn);
|
|
lsn_t i_last_lsn = cdio_cddap_track_lastsector(d, i_track);
|
|
|
|
/* For demo purposes we'll read only 300 frames (about 4
|
|
seconds). We don't want this to take too long. On the other
|
|
hand, I suppose it should be something close to a real test.
|
|
*/
|
|
if ( i_last_lsn - i_first_lsn > 300) i_last_lsn = i_first_lsn + 299;
|
|
|
|
printf("Reading track %d from LSN %ld to LSN %ld\n", i_track,
|
|
(long int) i_first_lsn, (long int) i_last_lsn);
|
|
|
|
/* Set reading mode for full paranoia, but allow skipping sectors. */
|
|
paranoia_modeset(p, PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP);
|
|
|
|
paranoia_seek(p, i_first_lsn, SEEK_SET);
|
|
|
|
for ( i_cursor = i_first_lsn; i_cursor <= i_last_lsn; i_cursor ++) @{
|
|
/* read a sector */
|
|
int16_t *p_readbuf=cdio_paranoia_read(p, NULL);
|
|
char *psz_err=cdio_cddap_errors(d);
|
|
char *psz_mes=cdio_cddap_messages(d);
|
|
|
|
if (psz_mes || psz_err)
|
|
printf("%s%s\n", psz_mes ? psz_mes: "", psz_err ? psz_err: "");
|
|
|
|
if (psz_err) free(psz_err);
|
|
if (psz_mes) free(psz_mes);
|
|
if( !p_readbuf ) @{
|
|
printf("paranoia read error. Stopping.\n");
|
|
break;
|
|
@}
|
|
@}
|
|
@}
|
|
cdio_paranoia_free(p);
|
|
@}
|
|
|
|
cdio_cdda_close(d);
|
|
|
|
exit(0);
|
|
@}
|
|
@end smallexample
|
|
|
|
Those who are die-hard cdparanoia programmers will notice that the
|
|
@value{libcdio} paranoia names are similar but a little bit
|
|
different. In particular instead of @code{paranoia_read} we have above
|
|
@code{cdio_paranoia_read} and instead of @code{cdda_open} we have
|
|
@code{cdio_cddap_open}.
|
|
|
|
This was done intentionally so that it is possible for the original
|
|
paranoia program can co-exist both in source code and linked libraries
|
|
and not conflict with @value{libcdio}'s paranoia source and libraries.
|
|
|
|
In general in place of any paranoia routine that begins
|
|
@code{paranoia_}, use @code{cdio_paranoia_} and in place of any
|
|
paranoia routine that begins @code{cdda_}, use @code{cdio_cddap_}. But
|
|
for a limited time @value{libcdio} will accept the old paranoia names
|
|
which may be useful for legacy paranoia code. The way this magic works
|
|
is by defining the old paranoia name to be the @value{libcdio} name.
|
|
|
|
In the unusual case where you do want to use both the original
|
|
paranoia and @value{libcdio} routines in a single source, the C
|
|
preprocessor symbol @code{DO_NOT_WANT_PARANOIA_COMPATIBILITY} can be
|
|
@code{define}'d and this disables the @code{#define} substitution done
|
|
automatically. The may still be a problem with conflicting structure
|
|
definitions like @code{cdrom_drive_t}.
|
|
|
|
@node All sample programs
|
|
@section A list of all sample programs in the @code{example} directory
|
|
|
|
The @code{example} directory contains some simple examples of the use
|
|
of the @value{libcdio} library.
|
|
|
|
A larger more-complicated example are the @command{cd-drive},
|
|
@command{cd-info}, @command{cd-read}, @command{iso-info} and
|
|
@command{iso-info} programs in the @command{src} directory.
|
|
|
|
Descriptions of the sample are as follows...
|
|
|
|
@table @code
|
|
|
|
@item @code{audio.c}
|
|
|
|
A program to show audio controls.
|
|
|
|
@item @code{cdchange.c}
|
|
|
|
A program to test if a CD has been changed since the last change test.
|
|
|
|
@item @code{cd-eject.c}
|
|
|
|
A a stripped-down "eject" command to open or close a CD-ROM tray.
|
|
|
|
@item @code{cdtext.c}
|
|
|
|
A program to show CD-Text and CD disc mode info.
|
|
|
|
@item @code{drives.c}
|
|
|
|
A program to show drivers installed and what the default CD-ROM drive
|
|
is and what CD drives are available.
|
|
|
|
@item @code{eject.c}
|
|
|
|
A program eject a CD from a CD-ROM drive and then close the door again.
|
|
|
|
@item @code{isofile.c}
|
|
|
|
A program to show using libiso9660 to extract a file from an ISO-9660 image.
|
|
|
|
@item @code{isofile2.c}
|
|
|
|
A program to show using libiso9660 to extract a file from a CDRWIN cue/bin CD image.
|
|
|
|
@item @code{C++/isofile2.cpp}
|
|
|
|
The same program as @code{isofile2.c} written in C++.
|
|
|
|
@item @code{isofuzzy.c}
|
|
|
|
A program showing fuzzy ISO-9660 detection/reading.
|
|
|
|
@item @code{isolist.c}
|
|
|
|
A program to show using @code{libiso9660} to list files in a
|
|
directory of an ISO-9660 image.
|
|
|
|
@item @code{C++/isolist.cpp}
|
|
|
|
The same program as @code{isolist.c} written in C++.
|
|
|
|
@item @code{C++/isolist.cpp}
|
|
|
|
The same program as @code{isolist.c} written in C++.
|
|
|
|
@item @code{isofuzzy.c}
|
|
|
|
A program showing fuzzy ISO-9660 detection/reading.
|
|
|
|
@item @code{mmc1.c}
|
|
|
|
A program to show issuing a simple MMC command (@code{INQUIRY}).
|
|
|
|
@item @code{C++/mmc1.cpp}
|
|
|
|
The same program as @code{mmc1.c} written in C++.
|
|
|
|
@item @code{mmc2.c}
|
|
|
|
A more involved MMC command to list CD and drive features from a
|
|
SCSI-MMC @code{GET_CONFIGURATION} command.
|
|
|
|
@item @code{mmc2a.c}
|
|
|
|
Prints MMC @command{MODE_SENSE} page 2A parameters.
|
|
Page 2a are the CD/DVD Capabilities and Mechanical Status.
|
|
|
|
@item @code{C++/mmc2.cpp}
|
|
|
|
The same program as @code{mmc2.c} written in C++.
|
|
|
|
@item @code{paranoia.c}
|
|
|
|
A program to show using libcdio's version of the CD-DA paranoia.
|
|
|
|
@item @code{paranoia2.c}
|
|
|
|
A program to show using libcdio's version of the CD-DA paranoia
|
|
library. But in this version, we'll open a cdio object before calling
|
|
paranoia's open. I imagine in many cases such as media players this
|
|
may be what will be done since, one may want to get CDDB/CD-Text info
|
|
beforehand.
|
|
|
|
@item @code{tracks.c}
|
|
|
|
A simple program to list track numbers and logical sector numbers of a
|
|
Compact Disc using @value{libcdio}.
|
|
|
|
@item @code{sample2.c}
|
|
|
|
A simple program to show drivers installed and what the default CD-ROM
|
|
drive is.
|
|
|
|
@item @code{sample3.c}
|
|
|
|
A simple program to show the use of @code{cdio_guess_cd_type()}. Figures out
|
|
the kind of CD image we've got.
|
|
|
|
@item @code{sample4.c}
|
|
|
|
A slightly improved sample3 program: we handle cdio logging and take
|
|
an optional CD-location.
|
|
|
|
@item @code{udf1.c}
|
|
|
|
A program to show using libudf to list files in a directory of an UDF
|
|
image.
|
|
|
|
@item @code{udf2.c}
|
|
|
|
A program to show using libudf to extract a file from an UDF image.
|
|
|
|
@end table
|
|
|
|
@node Utility Programs
|
|
@chapter Diagnostic programs: @command{cd-drive}, @command{cd-info}, @command{cd-read}, @command{iso-info}, @command{iso-read}
|
|
|
|
@menu
|
|
* cd-drive:: list out CD-ROM drive information
|
|
* cd-info:: list out CD or CD-image information
|
|
* cd-read:: read blocks of a CD or CD image
|
|
* iso-info:: list out ISO-9600 image information
|
|
* iso-read:: extract a file from an ISO 9660 image
|
|
@end menu
|
|
|
|
@node cd-drive
|
|
@section @samp{cd-drive}
|
|
|
|
@samp{cd-drive} lists out drive information, what features drive
|
|
supports, and information about what hardware drivers are available.
|
|
|
|
@node cd-info
|
|
@section @samp{cd-info}
|
|
|
|
@samp{cd-info} will print out the structure of a CD medium which could
|
|
either be a Compact Disc in a CD ROM or an CD image. It can try to
|
|
analyze the medium to give characteristics of the medium, such as how
|
|
many tracks are in the CD and the format of each track, whether a CD
|
|
contains a Video CD, CD-DA, PhotoCD, whether a track has an ISO-9660
|
|
filesystem.
|
|
|
|
@node cd-read
|
|
@section @samp{cd-read}
|
|
|
|
@samp{cd-info} can be used to read blocks a CD medium which could
|
|
either be a Compact Disc in a CD ROM or an CD image. You specify the
|
|
beginning and ending LSN and what mode format to use in the reading.
|
|
|
|
@node iso-info
|
|
@section @samp{iso-info}
|
|
|
|
@samp{iso-info} can be used to print out the structure of an ISO 9660
|
|
image.
|
|
|
|
@node iso-read
|
|
@section @samp{iso-read}
|
|
|
|
@samp{iso-read} can be used to extract a file in an ISO-9660 image.
|
|
|
|
@node CD-ROM Access and Drivers
|
|
@chapter CD-ROM Access and Drivers
|
|
|
|
@menu
|
|
* SCSI mess:: SCSI, SCSI commands, and MMC commands
|
|
* Access Modes:: Access Modes
|
|
* Accessing Driver Parameters:: Accessing Driver Parameters
|
|
|
|
* GNU/Linux:: GNU/Linux ioctl
|
|
* Microsoft:: Microsoft Windows ioctl and ASPI
|
|
* Solaris:: Solaris ATAPI and SCSI
|
|
* FreeBSD:: FreeBSD ioctl and CAM
|
|
* OS X:: OSX (non-exclussive access)
|
|
@end menu
|
|
|
|
@node SCSI mess
|
|
@section SCSI, SCSI commands, and MMC commands
|
|
|
|
Historically, SCSI referred to a class of hardware devices and device
|
|
controllers, bus technology and the data cables and protocols which
|
|
attached to such devices. This is now called ``Parallel SCSI''.
|
|
|
|
A specification standard grew out of the @emph{commands} that
|
|
controlled such SCSI devices, but now covers a wider variety of bus
|
|
technologies including Parallel SCSI, ATA/ATAPI, Serial ATA, Universal
|
|
Serial Bus (USB versions 1.1 and 2.0), and High Performance Serial Bus
|
|
(IEEE 1394, 1394A, and 1394B).
|
|
|
|
Another similar class of hardware devices and controllers is called ATA
|
|
and a command interface to that is called ATAPI (ATA Packetized
|
|
Interface). ATAPI provides a mechanism for transferring and executing
|
|
SCSI commands.
|
|
|
|
MMC (Multimedia commands) is a specification which adds special SCSI
|
|
commands for CD, DVD, Blu-Ray devices.
|
|
|
|
If your optical drive understands MMC commands as most do nowadays,
|
|
this probably gives the most flexibility in control. SCSI and ATAPI
|
|
CD-ROM devices generally support a fairly large set of MMC
|
|
commands. Unfortunately, on most Operating Systems one may need to do
|
|
some additional setup, such as install drivers or modules, to allow
|
|
access in this manner.
|
|
|
|
The name ``SCSI MMC'' is often found in the literature in
|
|
specifications and on the Internet. The ``SCSI'' part is probably a
|
|
little bit misleading because a drive can understand ``SCSI MMC''
|
|
commands but not use a SCSI bus protocol---ATAPI CD-ROMs are one such
|
|
broad class of examples. In fact there are drivers to ``encapsulate''
|
|
non-SCSI drives to make them act like more like SCSI drives, such as
|
|
by adding SCSI address naming.
|
|
|
|
For clarity and precision we will use the term ``MMC'' rather than
|
|
``SCSI MMC''.
|
|
|
|
One of the problems with MMC is that there are so many different
|
|
``standards''. In particular:
|
|
@itemize
|
|
@item MMC --- @url{ftp://ftp.t10.org/t10/drafts/mmc/},
|
|
@item MMC 2 --- @url{ftp://ftp.t10.org/t10/drafts/mmc2/}
|
|
@item MMC 3 --- @url{ftp://ftp.t10.org/t10/drafts/mmc3/}
|
|
@item MMC 4 --- @url{ftp://ftp.t10.org/t10/drafts/mmc4/}
|
|
@item MMC 5 --- @url{ftp://ftp.t10.org/t10/drafts/mmc5/}
|
|
@end itemize
|
|
along with the several ``drafts'' of these.
|
|
|
|
Another problem with the MMC commands related to the variations in
|
|
standards is the variation in the commands themselves and there are
|
|
perhaps two or three ways to do many of the basic commands like read a
|
|
CD frame.
|
|
|
|
There seems to be a fascination with the number of bytes a command
|
|
takes in the MMC-specification world. (Size matters?) So often the
|
|
name of an operation will have a suffix with the number of bytes of
|
|
the command (actually in MMC jargon this is called a ``CDB''
|
|
@cindex CDB (Command Descriptor Block)
|
|
or command descriptor block). So for example there is a 6-byte ``MODE
|
|
SELECT'' often called ``MODE SELECT 6'' and a 10-byte ``MODE SELECT''
|
|
often called ``MODE SELECT 10''. Presumably the 6-byte command came
|
|
first and it was discovered that there was some deficiency causing the
|
|
longer command. In @value{libcdio} where there are two formats we add
|
|
the suffix in the name, e.g. @code{CDIO_MMC_GPCMD_MODE_SELECT_6} or
|
|
@code{CDIO_MMC_GPCMD_MODE_SELECT_10}.
|
|
|
|
If the fascination and emphasis in the MMC specifications of CDB size
|
|
is a bit odd, equally so is the fact that this too often has bled
|
|
through at the OS programming API. However in @value{libcdio}, you
|
|
just give the opcode in @code{scsi_mmc_run_cmd()} and we'll do the
|
|
work to figure out how many bytes of the CDB are used.
|
|
|
|
Down the line it is hoped that @value{libcdio} will have a way to
|
|
remove a distinction between the various alternative and
|
|
alternative-size MMC commands. In @code{cdio/scsi-mmc.h} you will
|
|
find a little bit of this for example via the routine
|
|
@code{scsi_mmc_get_drive_cap()}. However much more work is needed.
|
|
|
|
Finally, in @code{libcdio} there is a driver access mode (not a
|
|
driver) called ``MMC''. It tells the specific drivers to use MMC
|
|
commands instead of other OS-specific mechanisms.
|
|
|
|
@node Access Modes
|
|
@section Access Modes
|
|
|
|
There are serveral ways that you can open a CD-ROM drive for
|
|
subsequent use. Each way is called an @emph{access
|
|
mode}. Historically libcdio only supported a reading kind of
|
|
access.
|
|
|
|
Adding the abilty to writing to a drive for ``burning'' is being added
|
|
by Thomas Schmitt, and this is accomplished by opening the drive in a
|
|
read-write mode. Currently writing modes are only supported via the
|
|
MMC command interface. Under this, one can get exclusive read-write
|
|
access or non-exclusive read-write access. The names of these two
|
|
modes are @code{MMC_RDWR_EXCL} and @code{MMC_RDWR} respectively.
|
|
|
|
On various OS's often there are two kinds of read modes that are
|
|
supported, one which uses MMC commands and one which uses some sort of
|
|
OS-specific native command interface. For example on Unix, there is
|
|
often a access mode associated with issuing an device-specific
|
|
@code{ioctl}'s that the OS supports.
|
|
|
|
To specify a particular kind of access mode, use @code{cdio_open_am}
|
|
which is like @code{cdio_open} but it requires one to specify an
|
|
access mode.
|
|
|
|
@node Accessing Driver Parameters
|
|
@section Accessing Driver Parameters --- @code{cdio_get_arg}
|
|
|
|
Once a driver is opened, you can use call @code{cdio_get_arg} to get
|
|
information about the driver. Each driver can have specific features
|
|
that can be queried, but there are features that are common to all
|
|
drivers. These are listed below:
|
|
|
|
@table @code
|
|
|
|
@item @code{access-mode}
|
|
This returns a string which is the name of the access mode in use.
|
|
@item @code{mmc-supported?}
|
|
This returns a string ``true'' or ``false'' depending whether the
|
|
driver with this access mode support MMC commands.
|
|
@item @code{scsi-tuple}
|
|
On drivers that support MMC commands, this returns the SCSI name or a
|
|
faked-up SCSI name that ripping front ends typically use.
|
|
@end table
|
|
|
|
@node GNU/Linux
|
|
@section GNU/Linux
|
|
|
|
The GNU/Linux uses a hybrid of methods. Somethings are done via ioctl
|
|
and some things via MMC. GNU/Linux has a rather nice and complete
|
|
ioctl mechanism. On the other hand, the MMC mechanism is more
|
|
universal. There are other ``access modes'' listed which are not
|
|
really access modes and should probably be redone/rethought. They are
|
|
just different ways to run the read command. But for completeness
|
|
These are ``READ_CD'' and ``READ_10''.
|
|
|
|
Writing/burning to a drive is supported via access modes
|
|
@code{MMC_RDWR_EXCL} or @code{MMC_RDWR}.
|
|
|
|
@node Microsoft
|
|
@section Microsoft Windows ioctl and ASPI
|
|
|
|
There are two CD drive access methods on Microsoft Windows platforms:
|
|
ioctl and ASPI.
|
|
|
|
The ASPI interface specification was developed by Adaptec for sending
|
|
commands to a SCSI host adapter (such as those controlling CD and DVD
|
|
drives) and used on Window 9x/NT and later. Emulation for ATAPI drives
|
|
was added so that the same sets of commands worked those even though
|
|
the drives might not be SCSI nor might there even be a SCSI controller
|
|
attached. The DLL is not part of Microsoft Windows and has to be
|
|
downloaded and installed separately.
|
|
|
|
However in Windows NT/2K/XP, Microsoft provides their Win32 ioctl
|
|
interface, and has taken steps to make using ASPI more inaccessible
|
|
(e.g. requiring administrative access to use ASPI).
|
|
|
|
|
|
@node Solaris
|
|
@section Solaris ATAPI and SCSI
|
|
|
|
There is currently only one CD drive access methods in Solaris: SCSI
|
|
(called ``USCSI'' or ``user SCSI'' in Solaris). There used to be an
|
|
ATAPI method and it could be resurrected if needed. USCSI was
|
|
preferred since on newer releases of Solaris and Solaris environments
|
|
one need to have root access for ATAPI.
|
|
|
|
@node FreeBSD
|
|
@section FreeBSD ioctl and CAM
|
|
|
|
There are two classes of access methods on FreeBSD: ioctl and CAM
|
|
(common access method). CAM is preferred when possible, especially on
|
|
newer releases. However CAM is right now sort of a hybrid and includes
|
|
some ioctl code.
|
|
|
|
Writing/burning to a drive is supported via access modes
|
|
@code{MMC_RDWR_EXCL} or @code{MMC_RDWR} which underneath use CAM access.
|
|
|
|
@node OS X
|
|
@section OS X (non-exclusive access)
|
|
|
|
A problem with libcdio on OS/X is that if the OS thinks it understands
|
|
the drive, it will get exclusive access to the drive and thus prevents
|
|
a library like this from obtaining non-exclusive access.
|
|
|
|
Currently @value{libcdio} access the CD-ROM non-exclusively. However
|
|
in order to be able to issue MMC, the current belief is that
|
|
exclusive access is needed. Probably in a future @value{libcdio},
|
|
there will be some way to specify which kind of access is desired
|
|
(with the inherent consequences of each).
|
|
|
|
More work on this driver is needed. Volunteers?
|
|
|
|
@node Internal Program Organization
|
|
@chapter Internal Program Organization
|
|
|
|
@menu
|
|
* File Organization::
|
|
* Library Organization::
|
|
* Programming Conventions::
|
|
@end menu
|
|
|
|
@node File Organization
|
|
@section File Organization
|
|
|
|
Here is a list of @value{libcdio} directories.
|
|
|
|
@itemize
|
|
|
|
@item @code{include/cdio}
|
|
|
|
This contains the headers that are public. One that will probably be
|
|
used quite a bit is @code{<cdio/cdio.h>}.
|
|
|
|
@item @code{lib}
|
|
|
|
Code for installed libraries. See below for further breakout
|
|
|
|
@item @code{lib/driver}
|
|
|
|
Code for various OS-specific CD-ROM drivers, image drivers, and
|
|
common MMC routines.
|
|
|
|
This code comprises @code{libcdio.a} (or the shared version of it).
|
|
|
|
@item @code{lib/iso9660}
|
|
|
|
Code for to extract or query ISO-9660 images.
|
|
|
|
This code comprises @code{libiso9660.a} (or the shared version of it).
|
|
|
|
@item @code{lib/paranoia}
|
|
|
|
This is from cdparanoia. It is the OS- and hardware- dependent code to
|
|
detect and correct jitter for CD-DA CDs.
|
|
|
|
@item @code{lib/cdda_interface}
|
|
|
|
This is also from cdparanoia. It is the OS- and hardware- independent
|
|
code to detect and correct jitter for CD-DA CDs.
|
|
|
|
@item @code{doc}
|
|
|
|
A home for fine documentation such as this masterpiece.
|
|
|
|
@item @code{example}
|
|
|
|
Here you will find various small example programs using
|
|
@value{libcdio} which are largely for pedagogical purposes. You might
|
|
be able to find one that is similar to what you want to do that could
|
|
be extended. In fact some these are contain the kernel ideas behind of
|
|
some of the larger programs in @file{src}.
|
|
|
|
@item @code{src}
|
|
|
|
Various stand-alone utility programs. See below.
|
|
|
|
@item @code{src/paranoia}
|
|
|
|
@value{libcdio}'s version of @code{cdparanoia}. Except for the fact
|
|
that the back-end CD-reading code has been replaced by
|
|
@value{libcdio}'s routines the code is pretty much identical.
|
|
|
|
@item @code{test}
|
|
|
|
Regression tests
|
|
|
|
@item @code{test/data}
|
|
|
|
Disk images and image meta-data used in tests
|
|
|
|
|
|
@item @code{test/driver}
|
|
|
|
Unit tests centered around the libcdio library (@code{libcdio}, source
|
|
location @code{lib/driver}
|
|
|
|
@end itemize
|
|
|
|
@node Library Organization
|
|
@section Library Organization
|
|
|
|
@menu
|
|
* libcdio::
|
|
* libcdio_cdda:: Access to CD-DA via the CD Paranoia library
|
|
* libcdio_paranoia:: Access to the CD Paranoia library
|
|
* libiso9660:: Access to ISO 9660 file systems and structures
|
|
* libudf:: Access to UDF file systems and structures
|
|
@end menu
|
|
|
|
@node libcdio
|
|
@subsection @samp{libcdio}
|
|
|
|
@value{libcdio} exports one opaque type @code{CdIo_t}. Internally this
|
|
a structure containing an enumeration for the driver, a structure
|
|
containing function pointers and a generic ``environment'' pointer
|
|
which is passed as a parameter on a function call. See
|
|
@file{lib/driver/cdio_private.h}. The initialization routine for each
|
|
driver sets up the function pointers and allocates memory for the
|
|
environment. When a particular user-level cdio routine is called (e.g
|
|
@code{cdio_get_first_track_num} for lib/driver/track.c), the
|
|
environment pointer is passed to a device-specific routine which will
|
|
then cast this pointer into something of the appropriate type.
|
|
|
|
Because function pointers are used, there can be and is quite a bit
|
|
of sharing of common routines. Some of the common routines are found
|
|
in the file @file{lib/driver/_cdio_generic.c}.
|
|
|
|
Another set of routines that one is likely to find shared amongst
|
|
drivers are the MMC commands. These are located in
|
|
@file{lib/driver/scsi_mmc.c}.
|
|
|
|
There is not only an attempt to share functions but we've tried to create
|
|
a generic CD structure @code{generic_img_private_t} of file
|
|
@file{lib/driver/generic.h}. By putting information into a common
|
|
structure, we increase the likelihood of being able to have a common
|
|
routine to perform some sort of function.
|
|
|
|
The generic CD structure would also be useful in a utility to convert
|
|
one CD-image format to another. Basically the first image format is
|
|
``parsed'' into the common internal format and then from this
|
|
structure it is not parsed.
|
|
|
|
@node libcdio_cdda
|
|
@subsection @samp{libcdio_cdda}
|
|
|
|
This library is intended to give access CD-DA disks using Monty's
|
|
cd-paranoia library underneath.
|
|
|
|
To be completed....
|
|
|
|
@node libcdio_paranoia
|
|
@subsection @samp{libcdio_paranoia}
|
|
|
|
This library is intended to give access Monty's cd-paranoia
|
|
library. It is the gap detection and jitter correction part without
|
|
the part dealing with CD-DA reading.
|
|
|
|
To be completed....
|
|
|
|
@node libiso9660
|
|
@subsection @samp{libiso9660}
|
|
|
|
This library is intended to give access and manipulate a ISO-9600 file
|
|
image. One part of it is concerned with the the entire ISO-9660 file
|
|
system image, and the other part access routines for manipulating data
|
|
structures and fields that go into such an image.
|
|
|
|
|
|
To be completed....
|
|
|
|
@node libudf
|
|
@subsection @samp{libudf}
|
|
|
|
This library is intended to give access and manipulate a UDF file
|
|
image.
|
|
|
|
To be completed....
|
|
|
|
@node Programming Conventions
|
|
@section Programming Conventions
|
|
|
|
@menu
|
|
* Coding Conventions::
|
|
* Namespace Conventions::
|
|
@end menu
|
|
|
|
@node Coding Conventions
|
|
@subsection Coding Conventions
|
|
|
|
In @value{libcdio} there are a number of conventions used. If you
|
|
understand some of these conventions it may facilitate understanding
|
|
the code a little.
|
|
|
|
@node Namespace Conventions
|
|
@subsection Namespace Conventions
|
|
|
|
For the most part, the visible external @value{libcdio} names follow
|
|
conventions so as not to be confused with other applications or
|
|
libraries. If you understand these conventions, there will be little
|
|
or no chance that the names you use will conflict with @value{libcdio}
|
|
and @code{libiso9660} and vice versa.
|
|
|
|
All of the external @value{libcdio} C routines start out with
|
|
@code{cdio_}, e.g. @code{cdio_open}; as a corollary, the
|
|
@value{libcdio} CD-Paranoia routines start @code{cdio_cddap_},
|
|
e.g. @code{cdio_cddap_open}. @code{libiso9660} routines start
|
|
@code{iso9660_}, e.g. @code{iso9660_open}.
|
|
|
|
@value{libcdio} C-Preprocessor names generally start @code{CDIO_}, for
|
|
example @code{CDIO_CD_FRAMESIZE_RAW}; @code{libiso9660}
|
|
C-preprocessor names start @code{ISO9660_},
|
|
e.g. @code{ISO9660_FRAMESIZE}.
|
|
|
|
@subsubsection suffixes (type and structure names)
|
|
|
|
A few suffixes are used in type and structure names:
|
|
|
|
@itemize
|
|
|
|
@item @code{_e}
|
|
|
|
An enumeration tag. Generally though the same name will appear with the
|
|
@code{_t} suffix and probably that should be used instead.
|
|
|
|
@item @code{_s}
|
|
|
|
A structure tag. Generally though the same name will appear with the
|
|
@code{_t} suffix and probably that should be used instead.
|
|
|
|
@item @code{_t}
|
|
|
|
A type suffix.
|
|
|
|
@end itemize
|
|
|
|
@subsubsection prefixes (variable names)
|
|
|
|
A number of prefixes are used in variable names here's what they mean
|
|
|
|
@itemize
|
|
@item @code{i_}
|
|
|
|
An integer type of some sort. A variable of this ilk one might find
|
|
being iterated over in @code{for} loops or used as the index of an
|
|
array for example.
|
|
|
|
@item @code{b_}
|
|
|
|
A Boolean type of some sort. A variable of this ilk one might find
|
|
being in an @code{if} condition for example.
|
|
|
|
@item @code{p_}
|
|
|
|
A pointer of some sort. A variable of this ilk, say
|
|
@code{p_foo} one is like likely to see @code{*p_foo} or
|
|
@code{p_foo->...}.
|
|
|
|
@item @code{pp_}
|
|
|
|
A pointer to a pointer of some sort. A variable of this ilk, say
|
|
@code{pp_foo} one is like likely to see @code{**p_foo} or
|
|
@code{p_foo[x][y]} for example
|
|
|
|
@item @code{psz_}
|
|
|
|
A @code{char *} pointer of some sort. A variable of this ilk, say
|
|
@code{psz_foo} may be used in a string operation. For example
|
|
@code{printf(%s\n", psz_foo)} or @code{strdup(psz_foo)}.
|
|
|
|
@item @code{ppsz_}
|
|
|
|
A pointer to a @code{char *} pointer of some sort. A variable of this
|
|
ilk, say @code{ppsz_foo} is used for example to return a list of
|
|
CD-ROM device names
|
|
|
|
@end itemize
|
|
|
|
There are a some other naming conventions. Generally if a routine
|
|
name starts @code{cdio_}, e.g. @code{cdio_open}, then it is an
|
|
externally visible routine in @code{libcdio}. If a name starts
|
|
@code{iso9660_}, e.g. @code{iso9660_is_dchar} then it is an externally
|
|
visible routine in @code{libiso9660}. If a name starts
|
|
@code{scsi_mmc_}, e.g. @code{scsi_mmc_get_discmode}, then it is an
|
|
externally visible MMC routine. (We don't have a separate library for
|
|
this yet.
|
|
|
|
Names using entirely capital letters and that start @code{CDIO_} are
|
|
externally visible @code{#defines}.
|
|
|
|
|
|
@node ISO-9660 Character Sets
|
|
@appendix ISO-9660 Character Sets
|
|
|
|
For a description of where are used see @xref{ISO 9660 Level 1}.
|
|
|
|
@menu
|
|
* ISO646 d-Characters::
|
|
* ISO646 a-Characters::
|
|
@end menu
|
|
|
|
@node ISO646 d-Characters
|
|
@appendixsec ISO646 d-Characters
|
|
|
|
@example
|
|
| 0 1 2 3 4 5 6 7
|
|
--+-----------------
|
|
0 | 0 P
|
|
1 | 1 A Q
|
|
2 | 2 B R
|
|
3 | 3 C S
|
|
4 | 4 D T
|
|
5 | 5 E U
|
|
6 | 6 F V
|
|
7 | 7 G W
|
|
8 | 8 H X
|
|
9 | 9 I Y
|
|
a | J Z
|
|
b | K
|
|
c | L
|
|
d | M
|
|
e | N
|
|
f | O _
|
|
@end example
|
|
|
|
@node ISO646 a-Characters
|
|
@appendixsec ISO646 a-Characters
|
|
|
|
@example
|
|
| 0 1 2 3 4 5 6 7
|
|
--+-----------------
|
|
0 | 0 P
|
|
1 | ! 1 A Q
|
|
2 | " 2 B R
|
|
3 | 3 C S
|
|
4 | 4 D T
|
|
5 | % 5 E U
|
|
6 | & 6 F V
|
|
7 | ' 7 G W
|
|
8 | ( 8 H X
|
|
9 | ) 9 I Y
|
|
a | * : J Z
|
|
b | + ; K
|
|
c | , < L
|
|
d | - = M
|
|
e | . > N
|
|
f | / ? O _
|
|
@end example
|
|
|
|
@node Glossary
|
|
@appendix Glossary
|
|
|
|
@include glossary.texi
|
|
|
|
@node GNU Free Documentation License
|
|
@appendix GNU Free Documentation License
|
|
@cindex FDL, GNU Free Documentation License
|
|
|
|
@include fdl.texi
|
|
|
|
@node General Index
|
|
@unnumbered General Index
|
|
@printindex cp
|
|
|
|
@bye
|