Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > bb4034fe5c01663c50ccf1eb5169c1a5 > files > 31

libburn-devel-1.2.2-1.fc15.i686.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<title>libburn: Libburn Documentation Index</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<!-- Generated by Doxygen 1.7.4 -->
<div id="top">
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td style="padding-left: 0.5em;">
   <div id="projectname">libburn&#160;<span id="projectnumber">1.2.2</span></div>
  </td>
 </tr>
 </tbody>
</table>
</div>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li class="current"><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
    </ul>
  </div>
</div>
<div class="header">
  <div class="headertitle">
<div class="title">Libburn Documentation Index </div>  </div>
</div>
<div class="contents">
<div class="textblock"><dl class="author"><dt><b>Author:</b></dt><dd>Mario Danic, Thomas Schmitt</dd></dl>
<h2><a class="anchor" id="intro"></a>
Introduction</h2>
<p>Libburnia is an open-source project for reading, mastering and writing optical discs. This page is about its capability to handle optical media. For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD+R/DL, DVD-RW, DVD-R, DVD-R/DL, BD-R, BD-RE.</p>
<p>Our scope is currently Linux 2.4 and 2.6, or FreeBSD, or Solaris . For ports to other systems we would need : login on a development machine resp. an OS ithat is installable on an AMD 64-bit PC, advise from a system person about the equivalent of Linux sg or FreeBSD CAM, volunteers for testing of realistic use cases.</p>
<p>libburn is the library by which preformatted data get onto optical media. Its code is independent of cdrecord. Its DVD capabilities are learned from studying the code of dvd+rw-tools and MMC-5 specs. No code but only the pure SCSI knowledge has been taken from dvd+rw-tools, though.</p>
<p>cdrskin is a limited cdrecord compatibility wrapper for libburn. cdrecord is a powerful GPL'ed burn program included in Joerg Schilling's cdrtools. cdrskin strives to be a second source for the services traditionally provided by cdrecord. Additionally it provides libburn's DVD/BD capabilities, where only -sao is compatible with cdrecord. cdrskin does not contain any bytes copied from cdrecord's sources. Many bytes have been copied from the message output of cdrecord runs, though. See cdrskin/README for more.</p>
<p>The burn API example of libburn is named <a class="el" href="libburner_8c.html">test/libburner.c</a> . The API for media information inquiry is demonstrated in test/telltoc.c . Explore these examples if you look for inspiration.</p>
<p>SONAME: libburn.so.4 (since 0.3.4, March 2007),</p>
<h2><a class="anchor" id="using"></a>
Using libburn</h2>
<p>Our build system is based on autotools. User experience tells us that you will need at least autotools version 1.7.</p>
<p>To build libburn and its companion applications go into its toplevel directory and execute</p>
<ul>
<li>./bootstrap (needed if you downloaded from SVN)</li>
</ul>
<ul>
<li>./configure</li>
</ul>
<ul>
<li>make</li>
</ul>
<p>To make the libraries accessible for running resp. developing applications</p>
<ul>
<li>make install</li>
</ul>
<h2><a class="anchor" id="libburner"></a>
Libburner</h2>
<p>libburner is a minimal demo application for the library libburn (see: <a class="el" href="libburn_8h.html">libburn/libburn.h</a>) as provided on <a href="http://libburnia-project.org">http://libburnia-project.org</a> . It can list the available devices, can burn to recordable CD, DVD, or BD, can blank a CD-RW or DVD-RW, and can format unformatted DVD-RW, BD-R, or BD-RE.</p>
<p>It's main purpose, nevertheless, is to show you how to use libburn and also to serve the libburnia team as reference application. libburner does indeed define the standard way how above gestures can be implemented and stay upward compatible for a good while.</p>
<h3><a class="anchor" id="libburner-help"></a>
Libburner --help</h3>
<pre>
Usage: test/libburner
       [--drive address|driveno|"-"]  [--audio]
       [--blank_fast|--blank_full|--format]  [--try_to_simulate]
       [--multi]  [one or more imagefiles|"-"]
Examples
A bus scan (needs rw-permissions to see a drive):
  test/libburner --drive -
Burn a file to drive chosen by number, leave appendable:
  test/libburner --drive 0 --multi my_image_file
Burn a file to drive chosen by persistent address, close:
  test/libburner --drive /dev/hdc my_image_file
Blank a used CD-RW (is combinable with burning in one run):
  test/libburner --drive /dev/hdc --blank_fast
Blank a used DVD-RW (is combinable with burning in one run):
  test/libburner --drive /dev/hdc --blank_full
Format a DVD-RW, BD-RE or BD-R:
  test/libburner --drive /dev/hdc --format
Burn two audio tracks (to CD only):
  lame --decode -t /path/to/track1.mp3 track1.cd
  test/dewav /path/to/track2.wav -o track2.cd
  test/libburner --drive /dev/hdc --audio track1.cd track2.cd
Burn a compressed afio archive on-the-fly:
  ( cd my_directory ; find . -print | afio -oZ - ) | \
  test/libburner --drive /dev/hdc -
To be read from *not mounted* media via: afio -tvZ /dev/hdc
</pre><p> libburner has two companions, telltoc and dewav, which help to perform some peripheral tasks of burning.</p>
<p>telltoc prints a table of content (sessions, tracks and leadouts), it tells about type and state of media, and also is able to provide the necessary multi-session information for program mkisofs option -C. Especially helpful are its predictions with "Write multi" and "Write modes" where availability of "TAO" indicates that tracks of unpredicted length can be written. See: test/telltoc --help.</p>
<p>dewav extracts raw byte-swapped audio data from files of format .wav (MS WAVE) or .au (SUN Audio). See example in libburner --help.</p>
<h3><a class="anchor" id="libburner-source"></a>
Sourceode of libburner</h3>
<p>Click on blue names of functions, structures, variables, etc in oder to get to the according specs of libburn API or libburner sourcecode.</p>
<div class="fragment"><pre class="fragment">
<span class="comment">/* test/libburner.c , API illustration of burning data or audio tracks to CD */</span>
<span class="comment">/* Copyright (C) 2005 - 2011 Thomas Schmitt &lt;scdbackup@gmx.net&gt; */</span>
<span class="comment">/* Provided under GPL, see also &quot;License and copyright aspects&quot; at file end */</span>

<span class="comment"></span>
<span class="comment">/**                               Overview </span>
<span class="comment">  </span>
<span class="comment">  libburner is a minimal demo application for the library libburn as provided</span>
<span class="comment">  on  http://libburnia-project.org . It can list the available devices, can</span>
<span class="comment">  blank a CD-RW or DVD-RW, can format DVD-RW and BD, can burn to CD-R,</span>
<span class="comment">  CD-RW, DVD-R, DVD+R, DVD+R/DL, DVD+RW, DVD-RW, DVD-RAM, BD-R, BD-RE. </span>
<span class="comment">  Not supported yet: DVD-R/DL.</span>
<span class="comment"></span>
<span class="comment">  It&#39;s main purpose, nevertheless, is to show you how to use libburn and also</span>
<span class="comment">  to serve the libburnia team as reference application. libburner.c does indeed</span>
<span class="comment">  define the standard way how above three gestures can be implemented and</span>
<span class="comment">  stay upward compatible for a good while.</span>
<span class="comment">  </span>
<span class="comment">  Before you can do anything, you have to initialize libburn by</span>
<span class="comment">     burn_initialize()</span>
<span class="comment">  and provide some signal and abort handling, e.g. by the builtin handler, by</span>
<span class="comment">     burn_set_signal_handling(&quot;libburner : &quot;, NULL, 0x0) </span>
<span class="comment">  as it is done in main() at the end of this file.</span>
<span class="comment">  Then you aquire a drive in an appropriate way conforming to the API. The twoi</span>
<span class="comment">  main approaches are shown here in application functions:</span>
<span class="comment">     libburner_aquire_by_adr()     demonstrates usage as of cdrecord traditions</span>
<span class="comment">     libburner_aquire_by_driveno()      demonstrates a scan-and-choose approach</span>
<span class="comment"></span>
<span class="comment">  With that aquired drive you can blank a CD-RW or DVD-RW as shown in</span>
<span class="comment">     libburner_blank_disc()</span>
<span class="comment">  or you can format a DVD-RW to profile &quot;Restricted Overwrite&quot; (needed once)</span>
<span class="comment">  or an unused BD to default size with spare blocks</span>
<span class="comment">     libburner_format()</span>
<span class="comment">  With the aquired drive you can burn to CD, DVD, BD. See</span>
<span class="comment">     libburner_payload()</span>
<span class="comment"></span>
<span class="comment">  These three functions switch temporarily to a non-fatal signal handler</span>
<span class="comment">  while they are waiting for the drive to become idle again:</span>
<span class="comment">     burn_set_signal_handling(&quot;libburner : &quot;, NULL, 0x30)</span>
<span class="comment">  After the waiting loop ended, they check for eventual abort events by</span>
<span class="comment">     burn_is_aborting(0)</span>
<span class="comment">  The 0x30 handler will eventually execute</span>
<span class="comment">     burn_abort()</span>
<span class="comment">  but not wait for the drive to become idle and not call exit().</span>
<span class="comment">  This is needed because the worker threads might block as long as the signal</span>
<span class="comment">  handler has not returned. The 0x0 handler would wait for them to finish.</span>
<span class="comment">  Take this into respect when implementing own signal handlers.</span>
<span class="comment"></span>
<span class="comment">  When everything is done, main() releases the drive and shuts down libburn:</span>
<span class="comment">     burn_drive_release();</span>
<span class="comment">     burn_finish()</span>
<span class="comment"></span>
<span class="comment">  Applications must use 64 bit off_t. E.g. by defining</span>
<span class="comment">    #define _LARGEFILE_SOURCE</span>
<span class="comment">    #define _FILE_OFFSET_BITS 64</span>
<span class="comment">  or take special precautions to interface with the library by 64 bit integers</span>
<span class="comment">  where libburn/libburn.h prescribes off_t.</span>
<span class="comment">  This program gets fed with appropriate settings externally by libburn&#39;s</span>
<span class="comment">  autotools generated build system.</span>
<span class="comment">*/</span>

<span class="comment"></span>
<span class="comment">/** See this for the decisive API specs . libburn.h is The Original */</span>
<span class="comment">/*  For using the installed header file :  #include &lt;libburn/libburn.h&gt; */</span>
<span class="comment">/*  This program insists in the own headerfile. */</span>
<span class="preprocessor">#include &quot;../libburn/libburn.h&quot;</span>

<span class="comment">/* libburn works on Linux systems with kernel 2.4 or 2.6, FreeBSD, Solaris */</span>
<span class="preprocessor">#include &lt;stdio.h&gt;</span>
<span class="preprocessor">#include &lt;ctype.h&gt;</span>
<span class="preprocessor">#include &lt;sys/types.h&gt;</span>
<span class="preprocessor">#include &lt;unistd.h&gt;</span>
<span class="preprocessor">#include &lt;string.h&gt;</span>
<span class="preprocessor">#include &lt;stdlib.h&gt;</span>
<span class="preprocessor">#include &lt;time.h&gt;</span>
<span class="preprocessor">#include &lt;errno.h&gt;</span>
<span class="preprocessor">#include &lt;sys/stat.h&gt;</span>
<span class="preprocessor">#include &lt;fcntl.h&gt;</span>

<span class="comment"></span>
<span class="comment">/** For simplicity i use global variables to represent the drives.</span>
<span class="comment">    Drives are systemwide global, so we do not give away much of good style.</span>
<span class="comment">*/</span>
<span class="comment"></span>
<span class="comment">/** This list will hold the drives known to libburn. This might be all CD</span>
<span class="comment">    drives of the system and thus might impose severe impact on the system.</span>
<span class="comment">*/</span>
<span class="keyword">static</span> <span class="keyword">struct </span><a class="code" href="structburn__drive__info.html" title="Information on a drive in the system.">burn_drive_info</a> *<a class="code" href="libburner_8c.html#a271c6b9f59f56d3ac45a173461f3eeba" title="Overview.">drive_list</a>;
<span class="comment"></span>
<span class="comment">/** If you start a long lasting operation with drive_count &gt; 1 then you are</span>
<span class="comment">    not friendly to the users of other drives on those systems. Beware. */</span>
<span class="keyword">static</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a2ab10011f756aef24f3168d95a5b439b" title="If you start a long lasting operation with drive_count &gt; 1 then you are not friendly to the users of ...">drive_count</a>;
<span class="comment"></span>
<span class="comment">/** This variable indicates wether the drive is grabbed and must be</span>
<span class="comment">    finally released */</span>
<span class="keyword">static</span> <span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#aaee536e445f55d19bfeb431850ec90e4" title="This variable indicates wether the drive is grabbed and must be finally released.">drive_is_grabbed</a> = 0;
<span class="comment"></span>
<span class="comment">/** A number and a text describing the type of media in aquired drive */</span>
<span class="keyword">static</span> <span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a>= -1;
<span class="keyword">static</span> <span class="keywordtype">char</span> <a class="code" href="libburner_8c.html#a14fb7b17efb56d94fb7d794053ae045b">current_profile_name</a>[80]= {<span class="stringliteral">&quot;&quot;</span>};


<span class="comment">/* Some in-advance definitions to allow a more comprehensive ordering</span>
<span class="comment">   of the functions and their explanations in here */</span>
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a3ed4822421dfb49c359b85accd952b56" title="If the persistent drive address is known, then this approach is much more un-obtrusive to the systemw...">libburner_aquire_by_adr</a>(<span class="keywordtype">char</span> *<a class="code" href="libburner_8c.html#adbe410a004b2aefa8868608beb2e5df1" title="The setup parameters of libburner.">drive_adr</a>);
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#aa2de071d4fb803b4a171dbc8dc14be5c" title="This method demonstrates how to use libburn without knowing a persistent drive address in advance...">libburner_aquire_by_driveno</a>(<span class="keywordtype">int</span> *drive_no);


<span class="comment">/* ------------------------------- API gestures ---------------------------- */</span>
<span class="comment"></span>
<span class="comment">/** You need to aquire a drive before burning. The API offers this as one</span>
<span class="comment">    compact call and alternatively as application controllable gestures of</span>
<span class="comment">    whitelisting, scanning for drives and finally grabbing one of them.</span>
<span class="comment"></span>
<span class="comment">    If you have a persistent address of the drive, then the compact call is</span>
<span class="comment">    to prefer because it only touches one drive. On modern Linux kernels,</span>
<span class="comment">    there should be no fatal disturbance of ongoing burns of other libburn</span>
<span class="comment">    instances with any of our approaches. We use open(O_EXCL) by default.</span>
<span class="comment">    On /dev/hdX it should cooperate with growisofs and some cdrecord variants.</span>
<span class="comment">    On /dev/sgN versus /dev/scdM expect it not to respect other programs.</span>
<span class="comment">*/</span>
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#ab485e1b9ba9572fb7596ffa6d6ff67c7" title="You need to aquire a drive before burning.">libburner_aquire_drive</a>(<span class="keywordtype">char</span> *<a class="code" href="libburner_8c.html#adbe410a004b2aefa8868608beb2e5df1" title="The setup parameters of libburner.">drive_adr</a>, <span class="keywordtype">int</span> *<a class="code" href="libburner_8c.html#ae62e41d8013871fadd6094bf505bf0e3">driveno</a>)
{
    <span class="keywordtype">int</span> ret;

    <span class="keywordflow">if</span>(drive_adr != NULL &amp;&amp; drive_adr[0] != 0)
        ret = <a class="code" href="libburner_8c.html#a3ed4822421dfb49c359b85accd952b56" title="If the persistent drive address is known, then this approach is much more un-obtrusive to the systemw...">libburner_aquire_by_adr</a>(drive_adr);
    <span class="keywordflow">else</span>
        ret = <a class="code" href="libburner_8c.html#aa2de071d4fb803b4a171dbc8dc14be5c" title="This method demonstrates how to use libburn without knowing a persistent drive address in advance...">libburner_aquire_by_driveno</a>(driveno);
    <span class="keywordflow">if</span> (ret &lt;= 0 || *driveno &lt;= 0)
        <span class="keywordflow">return</span> ret;
    <a class="code" href="libburn_8h.html#a1627c70c71ec5b6116f8d9d63d229285" title="Tells the MMC Profile identifier of the loaded media.">burn_disc_get_profile</a>(drive_list[0].<a class="code" href="structburn__drive__info.html#aa53408d48157a07e48b114e6c95550d0" title="The value by which this drive can be indexed when using functions in the library.">drive</a>, &amp;<a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a>,
                 <a class="code" href="libburner_8c.html#a14fb7b17efb56d94fb7d794053ae045b">current_profile_name</a>);
    <span class="keywordflow">if</span> (<a class="code" href="libburner_8c.html#a14fb7b17efb56d94fb7d794053ae045b">current_profile_name</a>[0])
        printf(<span class="stringliteral">&quot;Detected media type: %s\n&quot;</span>, <a class="code" href="libburner_8c.html#a14fb7b17efb56d94fb7d794053ae045b">current_profile_name</a>);
    <span class="keywordflow">return</span> 1;
}

<span class="comment"></span>
<span class="comment">/** If the persistent drive address is known, then this approach is much</span>
<span class="comment">    more un-obtrusive to the systemwide livestock of drives. Only the</span>
<span class="comment">    given drive device will be opened during this procedure.</span>
<span class="comment">*/</span>
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a3ed4822421dfb49c359b85accd952b56" title="If the persistent drive address is known, then this approach is much more un-obtrusive to the systemw...">libburner_aquire_by_adr</a>(<span class="keywordtype">char</span> *drive_adr)
{
    <span class="keywordtype">int</span> ret;
    <span class="keywordtype">char</span> libburn_drive_adr[<a class="code" href="libburn_8h.html#a489ca2111726a034324275aca4ed069c" title="Maximum length+1 to expect with a drive device file address string.">BURN_DRIVE_ADR_LEN</a>];

    <span class="comment">/* Some not-so-harmless drive addresses get blocked in this demo */</span>
    <span class="keywordflow">if</span> (strncmp(drive_adr, <span class="stringliteral">&quot;stdio:/dev/fd/&quot;</span>, 14) == 0 ||
        strcmp(drive_adr, <span class="stringliteral">&quot;stdio:-&quot;</span>) == 0) {
        fprintf(stderr, <span class="stringliteral">&quot;Will not work with pseudo-drive &#39;%s&#39;\n&quot;</span>,
            drive_adr);
        <span class="keywordflow">return</span> 0;
    }

    <span class="comment">/* This tries to resolve links or alternative device files */</span>
    ret = <a class="code" href="libburn_8h.html#a1b0e38d691eeb1da5f34a6ef0cc052bc" title="Try to convert a given existing filesystem address into a drive device file address.">burn_drive_convert_fs_adr</a>(drive_adr, libburn_drive_adr);  
    <span class="keywordflow">if</span> (ret&lt;=0) {
        fprintf(stderr, <span class="stringliteral">&quot;Address does not lead to a CD burner: &#39;%s&#39;\n&quot;</span>,
                 drive_adr);
        <span class="keywordflow">return</span> 0;
    }
    fprintf(stderr,<span class="stringliteral">&quot;Aquiring drive &#39;%s&#39; ...\n&quot;</span>, libburn_drive_adr);
    ret = <a class="code" href="libburn_8h.html#ae9c75e892e445ff73c38579210ba06a9" title="Aquire a drive with known device file address.">burn_drive_scan_and_grab</a>(&amp;drive_list, libburn_drive_adr, 1);
    <span class="keywordflow">if</span> (ret &lt;= 0) {
        fprintf(stderr,<span class="stringliteral">&quot;FAILURE with persistent drive address  &#39;%s&#39;\n&quot;</span>,
            libburn_drive_adr);
    } <span class="keywordflow">else</span> {
        fprintf(stderr,<span class="stringliteral">&quot;Done\n&quot;</span>);
        <a class="code" href="libburner_8c.html#aaee536e445f55d19bfeb431850ec90e4" title="This variable indicates wether the drive is grabbed and must be finally released.">drive_is_grabbed</a> = 1;
    }
    <span class="keywordflow">return</span> ret;
}

<span class="comment"></span>
<span class="comment">/** This method demonstrates how to use libburn without knowing a persistent</span>
<span class="comment">    drive address in advance. It has to make sure that after assessing the list</span>
<span class="comment">    of available drives, all unwanted drives get closed again. As long as they</span>
<span class="comment">    are open, no other libburn instance can see them. This is an intended</span>
<span class="comment">    locking feature. The application is responsible for giving up the locks</span>
<span class="comment">    by either burn_drive_release() (only after burn_drive_grab() !),</span>
<span class="comment">    burn_drive_info_forget(), burn_drive_info_free(), or burn_finish().</span>
<span class="comment">    @param driveno the index number in libburn&#39;s drive list. This will get</span>
<span class="comment">                   set to 0 on success and will then be the drive index to</span>
<span class="comment">                   use in the further dourse of processing.</span>
<span class="comment">    @return 1 success , &lt;= 0 failure</span>
<span class="comment">*/</span>
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#aa2de071d4fb803b4a171dbc8dc14be5c" title="This method demonstrates how to use libburn without knowing a persistent drive address in advance...">libburner_aquire_by_driveno</a>(<span class="keywordtype">int</span> *driveno)
{
    <span class="keywordtype">char</span> adr[<a class="code" href="libburn_8h.html#a489ca2111726a034324275aca4ed069c" title="Maximum length+1 to expect with a drive device file address string.">BURN_DRIVE_ADR_LEN</a>];
    <span class="keywordtype">int</span> ret, i;

    printf(<span class="stringliteral">&quot;Beginning to scan for devices ...\n&quot;</span>);
    <span class="keywordflow">while</span> (!<a class="code" href="libburn_8h.html#a21b480156713f0dbc8a254c24fa9689e" title="Scan for drives.">burn_drive_scan</a>(&amp;drive_list, &amp;<a class="code" href="libburner_8c.html#a2ab10011f756aef24f3168d95a5b439b" title="If you start a long lasting operation with drive_count &gt; 1 then you are not friendly to the users of ...">drive_count</a>))
        usleep(100002);
    <span class="keywordflow">if</span> (drive_count &lt;= 0 &amp;&amp; *driveno &gt;= 0) {
        printf(<span class="stringliteral">&quot;FAILED (no drives found)\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
    }
    printf(<span class="stringliteral">&quot;Done\n&quot;</span>);

    <span class="comment">/*</span>
<span class="comment">    Interactive programs may choose the drive number at this moment.</span>
<span class="comment"></span>
<span class="comment">    drive[0] to drive[drive_count-1] are struct burn_drive_info</span>
<span class="comment">    as defined in  libburn/libburn.h  . This structure is part of API</span>
<span class="comment">    and thus will strive for future compatibility on source level.</span>
<span class="comment">    Have a look at the info offered.</span>
<span class="comment">    Caution: do not take .location for drive address. Always use</span>
<span class="comment">        burn_drive_get_adr() or you might become incompatible</span>
<span class="comment">        in future.</span>
<span class="comment">    Note: bugs with struct burn_drive_info - if any - will not be</span>
<span class="comment">        easy to fix. Please report them but also strive for</span>
<span class="comment">        workarounds on application level.</span>
<span class="comment">    */</span>
    printf(<span class="stringliteral">&quot;\nOverview of accessible drives (%d found) :\n&quot;</span>,
        <a class="code" href="libburner_8c.html#a2ab10011f756aef24f3168d95a5b439b" title="If you start a long lasting operation with drive_count &gt; 1 then you are not friendly to the users of ...">drive_count</a>);
    printf(<span class="stringliteral">&quot;-----------------------------------------------------------------------------\n&quot;</span>);
    <span class="keywordflow">for</span> (i = 0; i &lt; (int) <a class="code" href="libburner_8c.html#a2ab10011f756aef24f3168d95a5b439b" title="If you start a long lasting operation with drive_count &gt; 1 then you are not friendly to the users of ...">drive_count</a>; i++) {
        <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a1ccfaccc7c7b10aa7f25bec20cf1b1b2" title="Inquire the device file address of a drive via a given drive_info object.">burn_drive_get_adr</a>(&amp;(drive_list[i]), adr) &lt;=0)
            strcpy(adr, <span class="stringliteral">&quot;-get_adr_failed-&quot;</span>);
        printf(<span class="stringliteral">&quot;%d  --drive &#39;%s&#39;  :  &#39;%s&#39;  &#39;%s&#39;\n&quot;</span>,
            i,adr,drive_list[i].<a class="code" href="structburn__drive__info.html#aff3ff7a51541d619f7f156ba58256992" title="Name of the vendor of the drive.">vendor</a>,drive_list[i].<a class="code" href="structburn__drive__info.html#a679639bfb29abb68d5b35269e935e88f" title="Name of the drive.">product</a>);
    }
    printf(<span class="stringliteral">&quot;-----------------------------------------------------------------------------\n\n&quot;</span>);

    <span class="comment">/*</span>
<span class="comment">    On multi-drive systems save yourself from sysadmins&#39; revenge.</span>
<span class="comment"></span>
<span class="comment">    Be aware that you hold reserved all available drives at this point.</span>
<span class="comment">    So either make your choice quick enough not to annoy other system</span>
<span class="comment">    users, or set free the drives for a while.</span>
<span class="comment"></span>
<span class="comment">    The tested way of setting free all drives is to shutdown the library</span>
<span class="comment">    and to restart when the choice has been made. The list of selectable</span>
<span class="comment">    drives should also hold persistent drive addresses as obtained</span>
<span class="comment">    above by burn_drive_get_adr(). By such an address one may use</span>
<span class="comment">    burn_drive_scan_and_grab() to finally aquire exactly one drive.</span>
<span class="comment"></span>
<span class="comment">    A not yet tested shortcut should be to call burn_drive_info_free()</span>
<span class="comment">    and to call either burn_drive_scan() or burn_drive_scan_and_grab()</span>
<span class="comment">    before accessing any drives again.</span>
<span class="comment"></span>
<span class="comment">    In both cases you have to be aware that the desired drive might get</span>
<span class="comment">    aquired in the meantime by another user resp. libburn process.</span>
<span class="comment">    */</span>

    <span class="comment">/* We already made our choice via command line. (default is 0)</span>
<span class="comment">       So we just have to keep our desired drive and drop all others.</span>
<span class="comment">       No other libburn instance will have a chance to steal our drive.</span>
<span class="comment">     */</span>
    <span class="keywordflow">if</span> (*driveno &lt; 0) {
        printf(<span class="stringliteral">&quot;Pseudo-drive \&quot;-\&quot; given : bus scanning done.\n&quot;</span>);
        <span class="keywordflow">return</span> 2; <span class="comment">/* the program will end after this */</span>
    }
    <span class="keywordflow">if</span> ((<span class="keywordtype">int</span>) <a class="code" href="libburner_8c.html#a2ab10011f756aef24f3168d95a5b439b" title="If you start a long lasting operation with drive_count &gt; 1 then you are not friendly to the users of ...">drive_count</a> &lt;= *driveno) {
        fprintf(stderr,
            <span class="stringliteral">&quot;Found only %d drives. Number %d not available.\n&quot;</span>,
            <a class="code" href="libburner_8c.html#a2ab10011f756aef24f3168d95a5b439b" title="If you start a long lasting operation with drive_count &gt; 1 then you are not friendly to the users of ...">drive_count</a>, *driveno);
        <span class="keywordflow">return</span> 0; <span class="comment">/* the program will end after this */</span>
    }

    <span class="comment">/* Drop all drives which we do not want to use */</span>
    <span class="keywordflow">for</span> (i = 0; i &lt; (int) <a class="code" href="libburner_8c.html#a2ab10011f756aef24f3168d95a5b439b" title="If you start a long lasting operation with drive_count &gt; 1 then you are not friendly to the users of ...">drive_count</a>; i++) {
        <span class="keywordflow">if</span> (i == *driveno) <span class="comment">/* the one drive we want to keep */</span>
    <span class="keywordflow">continue</span>;
        ret = <a class="code" href="libburn_8h.html#a9ac4cfc83330f237b6b3824e58039775" title="Release memory about a single drive and any exclusive lock on it.">burn_drive_info_forget</a>(&amp;(drive_list[i]),0);
        <span class="keywordflow">if</span> (ret != 1)
            fprintf(stderr, <span class="stringliteral">&quot;Cannot drop drive %d. Please report \&quot;ret=%d\&quot; to libburn-hackers@pykix.org\n&quot;</span>,
                i, ret);
        <span class="keywordflow">else</span>
            printf(<span class="stringliteral">&quot;Dropped unwanted drive %d\n&quot;</span>,i);
    }
    <span class="comment">/* Make the one we want ready for blanking or burning */</span>
    ret= <a class="code" href="libburn_8h.html#a392a1a309e906c35b8e2f31cc3f30969" title="Grab a drive.">burn_drive_grab</a>(drive_list[*driveno].<a class="code" href="structburn__drive__info.html#aa53408d48157a07e48b114e6c95550d0" title="The value by which this drive can be indexed when using functions in the library.">drive</a>, 1);
    <span class="keywordflow">if</span> (ret != 1)
        <span class="keywordflow">return</span> 0;
    <a class="code" href="libburner_8c.html#aaee536e445f55d19bfeb431850ec90e4" title="This variable indicates wether the drive is grabbed and must be finally released.">drive_is_grabbed</a> = 1;
    <span class="keywordflow">return</span> 1;
}

<span class="comment"></span>
<span class="comment">/** Makes a previously used CD-RW or unformatted DVD-RW ready for thorough</span>
<span class="comment">    re-usal.</span>
<span class="comment"></span>
<span class="comment">    To our knowledge it is hardly possible to abort an ongoing blank operation</span>
<span class="comment">    because after start it is entirely handled by the drive.</span>
<span class="comment">    So expect signal handling to wait the normal blanking timespan until it</span>
<span class="comment">    can allow the process to end. External kill -9 will not help the drive.</span>
<span class="comment">*/</span>
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a0d4b7dff006b3f1f2aac1acc48ba99df" title="Makes a previously used CD-RW or unformatted DVD-RW ready for thorough re-usal.">libburner_blank_disc</a>(<span class="keyword">struct</span> burn_drive *<a class="code" href="structburn__drive__info.html#aa53408d48157a07e48b114e6c95550d0" title="The value by which this drive can be indexed when using functions in the library.">drive</a>, <span class="keywordtype">int</span> blank_fast)
{
    <span class="keyword">enum</span> <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54" title="Possible status of the drive in regard to the disc in it.">burn_disc_status</a> disc_state;
    <span class="keyword">struct </span><a class="code" href="structburn__progress.html" title="Operation progress report.">burn_progress</a> p;
    <span class="keywordtype">double</span> percent = 1.0;

    disc_state = <a class="code" href="libburn_8h.html#ac009cc9dfe07c8c0b67f528a369fd511" title="Returns what kind of disc a drive is holding.">burn_disc_get_status</a>(drive);
    printf(
        <span class="stringliteral">&quot;Drive media status:  %d  (see  libburn/libburn.h  BURN_DISC_*)\n&quot;</span>,
        disc_state);
    <span class="keywordflow">if</span> (<a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x13) {
        ; <span class="comment">/* formatted DVD-RW will get blanked to sequential state */</span>
    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (disc_state == <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54a59c757934ef338281512efce4ab6fd93" title="The drive holds a blank disc.">BURN_DISC_BLANK</a>) {
        fprintf(stderr,
          <span class="stringliteral">&quot;IDLE: Blank media detected. Will leave it untouched\n&quot;</span>);
        <span class="keywordflow">return</span> 2;
    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (disc_state == <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54ae0ea0a584e319ee775062c88975c93cd" title="There is a disc with data on it in the drive.">BURN_DISC_FULL</a> ||
           disc_state == <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54acda6fac8462fa9affb4bff80daa2ab3f" title="There is an incomplete disc in the drive.">BURN_DISC_APPENDABLE</a>) {
        ; <span class="comment">/* this is what libburner is willing to blank */</span>
    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (disc_state == <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54a23eef5011f3aa95ce1858a2930c22c69" title="There is no disc at all in the drive.">BURN_DISC_EMPTY</a>) {
        fprintf(stderr,<span class="stringliteral">&quot;FATAL: No media detected in drive\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
    } <span class="keywordflow">else</span> {
        fprintf(stderr,
            <span class="stringliteral">&quot;FATAL: Unsuitable drive and media state\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
    }
    <span class="keywordflow">if</span>(!<a class="code" href="libburn_8h.html#a7838224062ed72305f3c6b1055cb1a98" title="Tells whether a disc can be erased or not.">burn_disc_erasable</a>(drive)) {
        fprintf(stderr,
            <span class="stringliteral">&quot;FATAL : Media is not of erasable type\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
    }
    <span class="comment">/* Switch to asynchronous signal handling for the time of waiting */</span>
    <a class="code" href="libburn_8h.html#a47b6e05ca3f53ca00f0ef4103eb5cd18" title="Control built-in signal handling.">burn_set_signal_handling</a>(<span class="stringliteral">&quot;libburner : &quot;</span>, NULL, 0x30);

    printf(<span class="stringliteral">&quot;Beginning to %s-blank media.\n&quot;</span>, (blank_fast?<span class="stringliteral">&quot;fast&quot;</span>:<span class="stringliteral">&quot;full&quot;</span>));
    <a class="code" href="libburn_8h.html#a86a5394e31ab522bca8cc5b7990f1923" title="Erase a disc in the drive.">burn_disc_erase</a>(drive, blank_fast);

    sleep(1);
    <span class="keywordflow">while</span> (<a class="code" href="libburn_8h.html#a992777abdf1f13f1e2c45271e43e9a3d" title="Returns the progress and status of a drive.">burn_drive_get_status</a>(drive, &amp;p) != <a class="code" href="libburn_8h.html#a3cb9c75648e773f63911b0975f67802badcb522cf8ccf1349e3d69826c3e1757f" title="The drive is not in an operation.">BURN_DRIVE_IDLE</a>) {
        <span class="keywordflow">if</span>(p.sectors&gt;0 &amp;&amp; p.sector&gt;=0) <span class="comment">/* display 1 to 99 percent */</span>
            percent = 1.0 + ((double) p.sector+1.0)
                     / ((double) p.sectors) * 98.0;
        printf(<span class="stringliteral">&quot;Blanking  ( %.1f%% done )\n&quot;</span>, percent);
        sleep(1);
    }
    <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a98a208e78cc9126a07d1bceea775f4db">burn_is_aborting</a>(0) &gt; 0)
        <span class="keywordflow">return</span> -1;
    <span class="comment">/* Back to synchronous handling */</span>
    <a class="code" href="libburn_8h.html#a47b6e05ca3f53ca00f0ef4103eb5cd18" title="Control built-in signal handling.">burn_set_signal_handling</a>(<span class="stringliteral">&quot;libburner : &quot;</span>, NULL, 0x0);
    printf(<span class="stringliteral">&quot;Done\n&quot;</span>);
    <span class="keywordflow">return</span> 1;
}

<span class="comment"></span>
<span class="comment">/** Formats unformatted DVD-RW to profile 0013h &quot;Restricted Overwrite&quot;</span>
<span class="comment">    which needs no blanking for re-use but is not capable of multi-session.</span>
<span class="comment">    Expect a behavior similar to blanking with unusual noises from the drive.</span>
<span class="comment"></span>
<span class="comment">    Formats unformatted BD-RE to default size. This will allocate some</span>
<span class="comment">    reserve space, test for bad blocks and make the media ready for writing.</span>
<span class="comment">    Expect a very long run time.</span>
<span class="comment"></span>
<span class="comment">    Formats unformatted blank BD-R to hold a default amount of spare blocks</span>
<span class="comment">    for eventual mishaps during writing. If BD-R get written without being</span>
<span class="comment">    formatted, then they get no such reserve and will burn at full speed.</span>
<span class="comment">*/</span>
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a42f03141c04bc55410fdc8e93c4f0143" title="Formats unformatted DVD-RW to profile 0013h &quot;Restricted Overwrite&quot; which needs no blanking for re-use...">libburner_format</a>(<span class="keyword">struct</span> burn_drive *drive)
{
    <span class="keyword">struct </span><a class="code" href="structburn__progress.html" title="Operation progress report.">burn_progress</a> p;
    <span class="keywordtype">double</span> percent = 1.0;
    <span class="keywordtype">int</span> ret, status, num_formats, format_flag= 0;
    off_t size = 0;
    <span class="keywordtype">unsigned</span> dummy;
    <span class="keyword">enum</span> <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54" title="Possible status of the drive in regard to the disc in it.">burn_disc_status</a> disc_state;

    <span class="keywordflow">if</span> (<a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x13) {
        fprintf(stderr, <span class="stringliteral">&quot;IDLE: DVD-RW media is already formatted\n&quot;</span>);
        <span class="keywordflow">return</span> 2;
    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x41 || <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x43) {
        disc_state = <a class="code" href="libburn_8h.html#ac009cc9dfe07c8c0b67f528a369fd511" title="Returns what kind of disc a drive is holding.">burn_disc_get_status</a>(drive);
        <span class="keywordflow">if</span> (disc_state != <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54a59c757934ef338281512efce4ab6fd93" title="The drive holds a blank disc.">BURN_DISC_BLANK</a> &amp;&amp; <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x41) {
            fprintf(stderr,
                <span class="stringliteral">&quot;FATAL: BD-R is not blank. Cannot format.\n&quot;</span>);
            <span class="keywordflow">return</span> 0;
        }
        ret = <a class="code" href="libburn_8h.html#abe718b844984771afe7c38f44e7abbe6" title="Inquire the formatting status, the associated sizes and the number of available formats.">burn_disc_get_formats</a>(drive, &amp;status, &amp;size, &amp;dummy,
                                &amp;num_formats);
        <span class="keywordflow">if</span> (ret &gt; 0 &amp;&amp; status != <a class="code" href="libburn_8h.html#a7b6978947a00d7f643003a1103b8a821" title="Possible formatting status values.">BURN_FORMAT_IS_UNFORMATTED</a>) {
            fprintf(stderr,
                <span class="stringliteral">&quot;IDLE: BD media is already formatted\n&quot;</span>);
            <span class="keywordflow">return</span> 2;
        }
        size = 0;           <span class="comment">/* does not really matter */</span>
        format_flag = 3&lt;&lt;1; <span class="comment">/* format to default size, no quick */</span>
    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (<a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x14) { <span class="comment">/* sequential DVD-RW */</span>
        size = 128 * 1024 * 1024;
        format_flag = 1; <span class="comment">/* write initial 128 MiB */</span>
    } <span class="keywordflow">else</span> {
        fprintf(stderr, <span class="stringliteral">&quot;FATAL: Can only format DVD-RW or BD\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
    }
    <a class="code" href="libburn_8h.html#a47b6e05ca3f53ca00f0ef4103eb5cd18" title="Control built-in signal handling.">burn_set_signal_handling</a>(<span class="stringliteral">&quot;libburner : &quot;</span>, NULL, 0x30);

    printf(<span class="stringliteral">&quot;Beginning to format media.\n&quot;</span>);
    <a class="code" href="libburn_8h.html#a1ac5250deb1dd13d7192f5e834fd5c4d" title="Format media for use with libburn.">burn_disc_format</a>(drive, size, format_flag);

    sleep(1);
    <span class="keywordflow">while</span> (<a class="code" href="libburn_8h.html#a992777abdf1f13f1e2c45271e43e9a3d" title="Returns the progress and status of a drive.">burn_drive_get_status</a>(drive, &amp;p) != <a class="code" href="libburn_8h.html#a3cb9c75648e773f63911b0975f67802badcb522cf8ccf1349e3d69826c3e1757f" title="The drive is not in an operation.">BURN_DRIVE_IDLE</a>) {
        <span class="keywordflow">if</span>(p.sectors&gt;0 &amp;&amp; p.sector&gt;=0) <span class="comment">/* display 1 to 99 percent */</span>
            percent = 1.0 + ((double) p.sector+1.0)
                     / ((double) p.sectors) * 98.0;
        printf(<span class="stringliteral">&quot;Formatting  ( %.1f%% done )\n&quot;</span>, percent);
        sleep(1);
    }
    <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a98a208e78cc9126a07d1bceea775f4db">burn_is_aborting</a>(0) &gt; 0)
        <span class="keywordflow">return</span> -1;
    <a class="code" href="libburn_8h.html#a47b6e05ca3f53ca00f0ef4103eb5cd18" title="Control built-in signal handling.">burn_set_signal_handling</a>(<span class="stringliteral">&quot;libburner : &quot;</span>, NULL, 0x0);
    <a class="code" href="libburn_8h.html#a1627c70c71ec5b6116f8d9d63d229285" title="Tells the MMC Profile identifier of the loaded media.">burn_disc_get_profile</a>(drive_list[0].drive, &amp;<a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a>,
                 <a class="code" href="libburner_8c.html#a14fb7b17efb56d94fb7d794053ae045b">current_profile_name</a>);
    <span class="keywordflow">if</span> (<a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x14 || <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x13)
        printf(<span class="stringliteral">&quot;Media type now: %4.4xh  \&quot;%s\&quot;\n&quot;</span>,
                 <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a>, <a class="code" href="libburner_8c.html#a14fb7b17efb56d94fb7d794053ae045b">current_profile_name</a>);
    <span class="keywordflow">if</span> (<a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> == 0x14) {
        fprintf(stderr,
          <span class="stringliteral">&quot;FATAL: Failed to change media profile to desired value\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
    }
    <span class="keywordflow">return</span> 1;
}

<span class="comment"></span>
<span class="comment">/** Brings preformatted track images (ISO 9660, audio, ...) onto media.</span>
<span class="comment">    To make sure a data image is fully readable on any Linux machine, this</span>
<span class="comment">    function adds 300 kiB of padding to the (usualy single) track.</span>
<span class="comment">    Audio tracks get padded to complete their last sector.</span>
<span class="comment">    A fifo of 4 MB is installed between each track and its data source.</span>
<span class="comment">    Each of the 4 MB buffers gets allocated automatically as soon as a track</span>
<span class="comment">    begins to be processed and it gets freed as soon as the track is done.</span>
<span class="comment">    The fifos do not wait for buffer fill but writing starts immediately.</span>
<span class="comment"></span>
<span class="comment">    In case of external signals expect abort handling of an ongoing burn to</span>
<span class="comment">    last up to a minute. Wait the normal burning timespan before any kill -9.</span>
<span class="comment"></span>
<span class="comment">    For simplicity, this function allows memory leaks in case of failure.</span>
<span class="comment">    In apps which do not abort immediately, one should clean up better.</span>
<span class="comment">*/</span>
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#af9c2fc57ed6d8505b22d377daef4914b" title="Brings preformatted track images (ISO 9660, audio, ...) onto media.">libburner_payload</a>(<span class="keyword">struct</span> burn_drive *drive, 
              <span class="keywordtype">char</span> <a class="code" href="libburner_8c.html#a20401aa73b1b1c04c3faddfd1647f302">source_adr</a>[][4096], <span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a896ce0b6e3a7f1c4aa381a351f45106b">source_adr_count</a>,
              <span class="keywordtype">int</span> multi, <span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a0987fdf0d2c39990a6de69c649f4d470">simulate_burn</a>, <span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#acdd017f7636e63e635f981e11aca9a22">all_tracks_type</a>)
{
    <span class="keyword">struct </span><a class="code" href="structburn__source.html" title="Data source interface for tracks.">burn_source</a> *data_src, *fifo_src[99];
    <span class="keyword">struct </span>burn_disc *target_disc;
    <span class="keyword">struct </span>burn_session *session;
    <span class="keyword">struct </span>burn_write_opts *burn_options;
    <span class="keyword">enum</span> <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54" title="Possible status of the drive in regard to the disc in it.">burn_disc_status</a> disc_state;
    <span class="keyword">struct </span>burn_track *track, *tracklist[99];
    <span class="keyword">struct </span><a class="code" href="structburn__progress.html" title="Operation progress report.">burn_progress</a> progress;
    time_t start_time;
    <span class="keywordtype">int</span> last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd;
    <span class="keywordtype">int</span> fifo_chunksize = 2352, fifo_chunks = 1783; <span class="comment">/* ~ 4 MB fifo */</span>
    off_t fixed_size;
    <span class="keywordtype">char</span> *adr, reasons[<a class="code" href="libburn_8h.html#a109ecdcd00fd30904a76c58040df9b79" title="The length of a rejection reasons string for burn_precheck_write() and burn_write_opts_auto_write_typ...">BURN_REASONS_LEN</a>];
    <span class="keyword">struct </span>stat stbuf;

    <span class="keywordflow">if</span> (all_tracks_type != <a class="code" href="libburn_8h.html#af52cf0d05e7e207ef4a06c9caad94d9f" title="Track mode - audio 2352 bytes per sector.">BURN_AUDIO</a>) {
        all_tracks_type = <a class="code" href="libburn_8h.html#af2e861349cb91c0af3a482225e3326ae" title="Track mode - mode 1 data 2048 bytes user data, and all the LEC money can buy.">BURN_MODE1</a>;
        <span class="comment">/* a padding of 300 kiB helps to avoid the read-ahead bug */</span>
        padding = 300*1024;
        fifo_chunksize = 2048;
        fifo_chunks = 2048; <span class="comment">/* 4 MB fifo */</span>
    }

    target_disc = <a class="code" href="libburn_8h.html#a9514679bfc2d3c3079bb06f0ddfc2216" title="Create a new disc.">burn_disc_create</a>();
    session = <a class="code" href="libburn_8h.html#a2dceb26e334833c240391cacfde555f7" title="Create a new session.">burn_session_create</a>();
    <a class="code" href="libburn_8h.html#a77730a5108688fbee754fea7b56e048a" title="Add a session to a disc at a specific position, increasing the sessions&#39;s reference count...">burn_disc_add_session</a>(target_disc, session, <a class="code" href="libburn_8h.html#a57aa6e45b0236acb5fbaa9f44280f6dc">BURN_POS_END</a>);

    <span class="keywordflow">for</span> (trackno = 0 ; trackno &lt; <a class="code" href="libburner_8c.html#a896ce0b6e3a7f1c4aa381a351f45106b">source_adr_count</a>; trackno++) {
      tracklist[trackno] = track = <a class="code" href="libburn_8h.html#aab87a2670415403982e499002fff0ca8" title="Create a track.">burn_track_create</a>();
      <a class="code" href="libburn_8h.html#aef2fd880f00065082691a848edcaf01e" title="Define the data in a track.">burn_track_define_data</a>(track, 0, padding, 1, all_tracks_type);

      <span class="comment">/* Open file descriptor to source of track data */</span>
      adr = source_adr[trackno];
      fixed_size = 0;
      <span class="keywordflow">if</span> (adr[0] == <span class="charliteral">&#39;-&#39;</span> &amp;&amp; adr[1] == 0) {
        fd = 0;
      } <span class="keywordflow">else</span> {
        fd = open(adr, O_RDONLY);
        <span class="keywordflow">if</span> (fd&gt;=0)
            <span class="keywordflow">if</span> (fstat(fd,&amp;stbuf)!=-1)
                <span class="keywordflow">if</span>((stbuf.st_mode&amp;S_IFMT)==S_IFREG)
                    fixed_size = stbuf.st_size;
      }
      <span class="keywordflow">if</span> (fixed_size==0)
        unpredicted_size = 1;

      <span class="comment">/* Convert this filedescriptor into a burn_source object */</span>
      data_src = NULL;
      <span class="keywordflow">if</span> (fd&gt;=0)
        data_src = <a class="code" href="libburn_8h.html#a2e1504f4c949b13cea988e31af9c150a" title="Creates a data source for an image file (a track) from an open readable filedescriptor, an eventually open readable subcodes file descriptor and eventually a fixed size in bytes.">burn_fd_source_new</a>(fd, -1, fixed_size);
      <span class="keywordflow">if</span> (data_src == NULL) {
        fprintf(stderr,
               <span class="stringliteral">&quot;FATAL: Could not open data source &#39;%s&#39;.\n&quot;</span>,adr);
        <span class="keywordflow">if</span>(errno!=0)
            fprintf(stderr,<span class="stringliteral">&quot;(Most recent system error: %s )\n&quot;</span>,
                strerror(errno));
        <span class="keywordflow">return</span> 0;
      }
      <span class="comment">/* Install a fifo object on top of that data source object */</span>
      fifo_src[trackno] = <a class="code" href="libburn_8h.html#a2d7a2faac8565ddd40d9e6ddae0bd922" title="Creates a fifo which acts as proxy for an already existing data source.">burn_fifo_source_new</a>(data_src,
                    fifo_chunksize, fifo_chunks, 0);
      <span class="keywordflow">if</span> (fifo_src[trackno] == NULL) {
        fprintf(stderr,
            <span class="stringliteral">&quot;FATAL: Could not create fifo object of 4 MB\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
      }

      <span class="comment">/* Use the fifo object as data source for the track */</span>
      <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a27400c91868946c04b013c2cc2ac632a" title="Set the track&#39;s data source.">burn_track_set_source</a>(track, fifo_src[trackno])
                             != <a class="code" href="libburn_8h.html#aa5ddf1fe21e47ff4d4a44262c1d7da9ba936b5414e25492f45a3f240941f3d9a1" title="The source is ok.">BURN_SOURCE_OK</a>) {
        fprintf(stderr,
               <span class="stringliteral">&quot;FATAL: Cannot attach source object to track object\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
      }

      <a class="code" href="libburn_8h.html#a2062793258361e9e84e7ddbf5f9ab06a" title="Add a track to a session at specified position.">burn_session_add_track</a>(session, track, <a class="code" href="libburn_8h.html#a57aa6e45b0236acb5fbaa9f44280f6dc">BURN_POS_END</a>);
      printf(<span class="stringliteral">&quot;Track %d : source is &#39;%s&#39;\n&quot;</span>, trackno+1, adr);

      <span class="comment">/* Give up local reference to the data burn_source object */</span>
      <a class="code" href="libburn_8h.html#a1a03f8b3088b8ce6305e7a48c3e034eb" title="Free a burn_source (decrease its refcount and maybe free it)">burn_source_free</a>(data_src);
      
    } <span class="comment">/* trackno loop end */</span>

    <span class="comment">/* Evaluate drive and media */</span>
    disc_state = <a class="code" href="libburn_8h.html#ac009cc9dfe07c8c0b67f528a369fd511" title="Returns what kind of disc a drive is holding.">burn_disc_get_status</a>(drive);
    <span class="keywordflow">if</span> (disc_state != <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54a59c757934ef338281512efce4ab6fd93" title="The drive holds a blank disc.">BURN_DISC_BLANK</a> &amp;&amp;
        disc_state != <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54acda6fac8462fa9affb4bff80daa2ab3f" title="There is an incomplete disc in the drive.">BURN_DISC_APPENDABLE</a>) {
        <span class="keywordflow">if</span> (disc_state == <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54ae0ea0a584e319ee775062c88975c93cd" title="There is a disc with data on it in the drive.">BURN_DISC_FULL</a>) {
            fprintf(stderr, <span class="stringliteral">&quot;FATAL: Closed media with data detected. Need blank or appendable media.\n&quot;</span>);
            <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a7838224062ed72305f3c6b1055cb1a98" title="Tells whether a disc can be erased or not.">burn_disc_erasable</a>(drive))
                fprintf(stderr, <span class="stringliteral">&quot;HINT: Try --blank_fast\n\n&quot;</span>);
        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (disc_state == <a class="code" href="libburn_8h.html#ad6002e7587373e7e9a9efbd22c1e6c54a23eef5011f3aa95ce1858a2930c22c69" title="There is no disc at all in the drive.">BURN_DISC_EMPTY</a>) 
            fprintf(stderr,<span class="stringliteral">&quot;FATAL: No media detected in drive\n&quot;</span>);
        <span class="keywordflow">else</span>
            fprintf(stderr,
             <span class="stringliteral">&quot;FATAL: Cannot recognize state of drive and media\n&quot;</span>);
        <span class="keywordflow">return</span> 0;
    }

    burn_options = <a class="code" href="libburn_8h.html#ad62ba8f5344c36e2faa9aa6208751e0a" title="Creates a write_opts struct for burning to the specified drive.">burn_write_opts_new</a>(drive);
    <a class="code" href="libburn_8h.html#a8e4ed29facd80f19c866b3686dea125f" title="Sets whether to use opc or not with the write_opts struct.">burn_write_opts_set_perform_opc</a>(burn_options, 0);
    <a class="code" href="libburn_8h.html#ad04dc50d1223d78a8e8c3134df96fd82" title="Sets the multi flag which eventually marks the emerging session as not being the last one and thus cr...">burn_write_opts_set_multi</a>(burn_options, !!multi);
    <span class="keywordflow">if</span>(simulate_burn)
        printf(<span class="stringliteral">&quot;\n*** Will TRY to SIMULATE burning ***\n\n&quot;</span>);
    <a class="code" href="libburn_8h.html#a05f68d91d1074a103fa8e17bb664b6d8" title="Sets the simulate value for the write_opts struct .">burn_write_opts_set_simulate</a>(burn_options, simulate_burn);
    <a class="code" href="libburn_8h.html#a62aa53e04ff9fb848178ab85d38a9c5a" title="Sets drive read and write speed Note: &quot;k&quot; is 1000, not 1024.">burn_drive_set_speed</a>(drive, 0, 0);
    <a class="code" href="libburn_8h.html#a3fdc2e3cc51bec2072ab91b99d4e52d9" title="Controls buffer underrun prevention.">burn_write_opts_set_underrun_proof</a>(burn_options, 1);
    <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a88a9d0adaf11e19cb4ed8b08f7740b5b" title="As an alternative to burn_write_opts_set_write_type() this function tries to find a suitable write ty...">burn_write_opts_auto_write_type</a>(burn_options, target_disc,
                    reasons, 0) == <a class="code" href="libburn_8h.html#a98506c0d72c878ea6cbecc4004451d9baf43fb685b48fdc83337465457eec54fd" title="In replies this indicates that not any writing will work.">BURN_WRITE_NONE</a>) {
        fprintf(stderr, <span class="stringliteral">&quot;FATAL: Failed to find a suitable write mode with this media.\n&quot;</span>);
        fprintf(stderr, <span class="stringliteral">&quot;Reasons given:\n%s\n&quot;</span>, reasons);
        <span class="keywordflow">return</span> 0;
    }
    <a class="code" href="libburn_8h.html#a47b6e05ca3f53ca00f0ef4103eb5cd18" title="Control built-in signal handling.">burn_set_signal_handling</a>(<span class="stringliteral">&quot;libburner : &quot;</span>, NULL, 0x30);

    printf(<span class="stringliteral">&quot;Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n&quot;</span>);
    start_time = time(0);
    <a class="code" href="libburn_8h.html#a75d3d59e9c3cd7cd42c9735bee83bd91" title="Write a disc in the drive.">burn_disc_write</a>(burn_options, target_disc);

    <a class="code" href="libburn_8h.html#a1336283a8e59fe7ac187243350e21866" title="Frees a write_opts struct created with burn_write_opts_new.">burn_write_opts_free</a>(burn_options);
    <span class="keywordflow">while</span> (<a class="code" href="libburn_8h.html#a992777abdf1f13f1e2c45271e43e9a3d" title="Returns the progress and status of a drive.">burn_drive_get_status</a>(drive, NULL) == <a class="code" href="libburn_8h.html#a3cb9c75648e773f63911b0975f67802ba9c16cf7335531f54df68a0b280c75898" title="The library is spawning the processes to handle a pending operation (A read/write/etc is about to sta...">BURN_DRIVE_SPAWNING</a>)
        usleep(100002);
    <span class="keywordflow">while</span> (<a class="code" href="libburn_8h.html#a992777abdf1f13f1e2c45271e43e9a3d" title="Returns the progress and status of a drive.">burn_drive_get_status</a>(drive, &amp;progress) != <a class="code" href="libburn_8h.html#a3cb9c75648e773f63911b0975f67802badcb522cf8ccf1349e3d69826c3e1757f" title="The drive is not in an operation.">BURN_DRIVE_IDLE</a>) {
        <span class="keywordflow">if</span> (progress.sectors &lt;= 0 ||
            (progress.sector &gt;= progress.sectors - 1 &amp;&amp;
                 !unpredicted_size) ||
            (unpredicted_size &amp;&amp; progress.sector == last_sector))
            printf(
                 <span class="stringliteral">&quot;Thank you for being patient since %d seconds.&quot;</span>,
                 (<span class="keywordtype">int</span>) (time(0) - start_time));
        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(unpredicted_size)
            printf(<span class="stringliteral">&quot;Track %d : sector %d&quot;</span>, progress.track+1,
                progress.sector);
        <span class="keywordflow">else</span>
            printf(<span class="stringliteral">&quot;Track %d : sector %d of %d&quot;</span>,progress.track+1,
                progress.sector, progress.sectors);
        last_sector = progress.sector;
        <span class="keywordflow">if</span> (progress.track &gt;= 0 &amp;&amp; progress.track &lt; source_adr_count) {
            <span class="keywordtype">int</span> size, free_bytes, ret;
            <span class="keywordtype">char</span> *status_text;
    
            ret = <a class="code" href="libburn_8h.html#af655df46b73a4d774cc1d27b0c57677d" title="Inquires state and fill parameters of a fifo burn_source which was created by burn_fifo_source_new() ...">burn_fifo_inquire_status</a>(
                fifo_src[progress.track], &amp;size, &amp;free_bytes,
                &amp;status_text);
            <span class="keywordflow">if</span> (ret &gt;= 0 ) 
                printf(<span class="stringliteral">&quot;  [fifo %s, %2d%% fill]&quot;</span>, status_text,
                    (<span class="keywordtype">int</span>) (100.0 - 100.0 *
                        ((<span class="keywordtype">double</span>) free_bytes) /
                        (<span class="keywordtype">double</span>) size));
        } 
        printf(<span class="stringliteral">&quot;\n&quot;</span>);
        sleep(1);
    }
    printf(<span class="stringliteral">&quot;\n&quot;</span>);

    <span class="keywordflow">for</span> (trackno = 0 ; trackno &lt; <a class="code" href="libburner_8c.html#a896ce0b6e3a7f1c4aa381a351f45106b">source_adr_count</a>; trackno++) {
        <a class="code" href="libburn_8h.html#a1a03f8b3088b8ce6305e7a48c3e034eb" title="Free a burn_source (decrease its refcount and maybe free it)">burn_source_free</a>(fifo_src[trackno]);
        <a class="code" href="libburn_8h.html#a105c516de4f9242d91f7e92d0b399110" title="Free a track.">burn_track_free</a>(tracklist[trackno]);
    }
    <a class="code" href="libburn_8h.html#a21765aec4a5b1a9c21c027f855f9c2a0" title="Free a session (and decrease reference count on all tracks inside)">burn_session_free</a>(session);
    <a class="code" href="libburn_8h.html#aca06a415d81da71a3fd3aad31e83c698" title="Delete disc and decrease the reference count on all its sessions.">burn_disc_free</a>(target_disc);
    <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a98a208e78cc9126a07d1bceea775f4db">burn_is_aborting</a>(0) &gt; 0)
        <span class="keywordflow">return</span> -1;
    <span class="keywordflow">if</span> (multi &amp;&amp; <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> != 0x1a &amp;&amp; <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> != 0x13 &amp;&amp;
        <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> != 0x12 &amp;&amp; <a class="code" href="libburner_8c.html#aa1a3fe5ef89cfc5713ab70e8b3d41043" title="A number and a text describing the type of media in aquired drive.">current_profile</a> != 0x43) 
            <span class="comment">/* not with DVD+RW, formatted DVD-RW, DVD-RAM, BD-RE */</span>
        printf(<span class="stringliteral">&quot;NOTE: Media left appendable.\n&quot;</span>);
    <span class="keywordflow">if</span> (simulate_burn)
        printf(<span class="stringliteral">&quot;\n*** Did TRY to SIMULATE burning ***\n\n&quot;</span>);
    <span class="keywordflow">return</span> 1;
}

<span class="comment"></span>
<span class="comment">/** The setup parameters of libburner */</span>
<span class="keyword">static</span> <span class="keywordtype">char</span> drive_adr[<a class="code" href="libburn_8h.html#a489ca2111726a034324275aca4ed069c" title="Maximum length+1 to expect with a drive device file address string.">BURN_DRIVE_ADR_LEN</a>] = {<span class="stringliteral">&quot;&quot;</span>};
<span class="keyword">static</span> <span class="keywordtype">int</span> driveno = 0;
<span class="keyword">static</span> <span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#aec8a1ef7e11653bc93fe1d5b2c63c9d3">do_blank</a> = 0;
<span class="keyword">static</span> <span class="keywordtype">char</span> source_adr[99][4096];
<span class="keyword">static</span> <span class="keywordtype">int</span> source_adr_count = 0;
<span class="keyword">static</span> <span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a8e824cc51e6e6cfc91ac1df7830a70ed">do_multi</a> = 0;
<span class="keyword">static</span> <span class="keywordtype">int</span> simulate_burn = 0;
<span class="keyword">static</span> <span class="keywordtype">int</span> all_tracks_type = <a class="code" href="libburn_8h.html#af2e861349cb91c0af3a482225e3326ae" title="Track mode - mode 1 data 2048 bytes user data, and all the LEC money can buy.">BURN_MODE1</a>;

<span class="comment"></span>
<span class="comment">/** Converts command line arguments into above setup parameters.</span>
<span class="comment">*/</span>
<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a67980a9cee509cf714f67aa96a47c75d" title="Converts command line arguments into above setup parameters.">libburner_setup</a>(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv)
{
    <span class="keywordtype">int</span> i, insuffient_parameters = 0, print_help = 0;

    <span class="keywordflow">for</span> (i = 1; i &lt; argc; ++i) {
        <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--audio&quot;</span>)) {
            all_tracks_type = <a class="code" href="libburn_8h.html#af52cf0d05e7e207ef4a06c9caad94d9f" title="Track mode - audio 2352 bytes per sector.">BURN_AUDIO</a>;

        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--blank_fast&quot;</span>)) {
            do_blank = 1;

        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--blank_full&quot;</span>)) {
            do_blank = 2;

        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--burn_for_real&quot;</span>)) {
            simulate_burn = 0;

        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--drive&quot;</span>)) {
            ++i;
            <span class="keywordflow">if</span> (i &gt;= argc) {
                fprintf(stderr,<span class="stringliteral">&quot;--drive requires an argument\n&quot;</span>);
                <span class="keywordflow">return</span> 1;
            } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (strcmp(argv[i], <span class="stringliteral">&quot;-&quot;</span>) == 0) {
                drive_adr[0] = 0;
                driveno = -1;
            } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (isdigit(argv[i][0])) {
                drive_adr[0] = 0;
                driveno = atoi(argv[i]);
            } <span class="keywordflow">else</span> {
                <span class="keywordflow">if</span>(strlen(argv[i]) &gt;= <a class="code" href="libburn_8h.html#a489ca2111726a034324275aca4ed069c" title="Maximum length+1 to expect with a drive device file address string.">BURN_DRIVE_ADR_LEN</a>) {
                    fprintf(stderr,<span class="stringliteral">&quot;--drive address too long (max. %d)\n&quot;</span>,
                            <a class="code" href="libburn_8h.html#a489ca2111726a034324275aca4ed069c" title="Maximum length+1 to expect with a drive device file address string.">BURN_DRIVE_ADR_LEN</a>-1);
                    <span class="keywordflow">return</span> 2;
                }
                strcpy(drive_adr, argv[i]);
            }
        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> ((!strcmp(argv[i], <span class="stringliteral">&quot;--format_overwrite&quot;</span>)) ||
           (!strcmp(argv[i], <span class="stringliteral">&quot;--format&quot;</span>))) {
            do_blank = 101;

        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--multi&quot;</span>)) {
        do_multi = 1;

    } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--stdin_size&quot;</span>)) { <span class="comment">/* obsoleted */</span>
        i++;

        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--try_to_simulate&quot;</span>)) {
            simulate_burn = 1;

        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strcmp(argv[i], <span class="stringliteral">&quot;--help&quot;</span>)) {
            print_help = 1;

        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!strncmp(argv[i], <span class="stringliteral">&quot;--&quot;</span>,2)) {
            fprintf(stderr, <span class="stringliteral">&quot;Unidentified option: %s\n&quot;</span>, argv[i]);
            <span class="keywordflow">return</span> 7;
        } <span class="keywordflow">else</span> {
            <span class="keywordflow">if</span>(strlen(argv[i]) &gt;= 4096) {
                fprintf(stderr, <span class="stringliteral">&quot;Source address too long (max. %d)\n&quot;</span>, 4096-1);
                <span class="keywordflow">return</span> 5;
            }
            <span class="keywordflow">if</span>(source_adr_count &gt;= 99) {
                fprintf(stderr, <span class="stringliteral">&quot;Too many tracks (max. 99)\n&quot;</span>);
                <span class="keywordflow">return</span> 6;
            }
            strcpy(source_adr[source_adr_count], argv[i]);
            source_adr_count++;
        }
    }
    insuffient_parameters = 1;
    <span class="keywordflow">if</span> (driveno &lt; 0)
        insuffient_parameters = 0;
    <span class="keywordflow">if</span> (source_adr_count &gt; 0)
        insuffient_parameters = 0; 
    <span class="keywordflow">if</span> (do_blank)
        insuffient_parameters = 0;
    <span class="keywordflow">if</span> (print_help || insuffient_parameters ) {
        printf(<span class="stringliteral">&quot;Usage: %s\n&quot;</span>, argv[0]);
        printf(<span class="stringliteral">&quot;       [--drive &lt;address&gt;|&lt;driveno&gt;|\&quot;-\&quot;]  [--audio]\n&quot;</span>);
        printf(<span class="stringliteral">&quot;       [--blank_fast|--blank_full|--format]  [--try_to_simulate]\n&quot;</span>);
        printf(<span class="stringliteral">&quot;       [--multi]  [&lt;one or more imagefiles&gt;|\&quot;-\&quot;]\n&quot;</span>);
        printf(<span class="stringliteral">&quot;Examples\n&quot;</span>);
        printf(<span class="stringliteral">&quot;A bus scan (needs rw-permissions to see a drive):\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  %s --drive -\n&quot;</span>,argv[0]);
        printf(<span class="stringliteral">&quot;Burn a file to drive chosen by number, leave appendable:\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  %s --drive 0 --multi my_image_file\n&quot;</span>, argv[0]);
        printf(<span class="stringliteral">&quot;Burn a file to drive chosen by persistent address, close:\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  %s --drive /dev/hdc my_image_file\n&quot;</span>, argv[0]);
        printf(<span class="stringliteral">&quot;Blank a used CD-RW (is combinable with burning in one run):\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  %s --drive /dev/hdc --blank_fast\n&quot;</span>,argv[0]);
        printf(<span class="stringliteral">&quot;Blank a used DVD-RW (is combinable with burning in one run):\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  %s --drive /dev/hdc --blank_full\n&quot;</span>,argv[0]);
        printf(<span class="stringliteral">&quot;Format a DVD-RW, BD-RE or BD-R:\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  %s --drive /dev/hdc --format\n&quot;</span>, argv[0]);
        printf(<span class="stringliteral">&quot;Burn two audio tracks (to CD only):\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  lame --decode -t /path/to/track1.mp3 track1.cd\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  test/dewav /path/to/track2.wav -o track2.cd\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  %s --drive /dev/hdc --audio track1.cd track2.cd\n&quot;</span>, argv[0]);
        printf(<span class="stringliteral">&quot;Burn a compressed afio archive on-the-fly:\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  ( cd my_directory ; find . -print | afio -oZ - ) | \\\n&quot;</span>);
        printf(<span class="stringliteral">&quot;  %s --drive /dev/hdc -\n&quot;</span>, argv[0]);
        printf(<span class="stringliteral">&quot;To be read from *not mounted* media via: afio -tvZ /dev/hdc\n&quot;</span>);
        <span class="keywordflow">if</span> (insuffient_parameters)
            <span class="keywordflow">return</span> 6;
    }
    <span class="keywordflow">return</span> 0;
}


<span class="keywordtype">int</span> <a class="code" href="libburner_8c.html#a3c04138a5bfe5d72780bb7e82a18e627">main</a>(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv)
{
    <span class="keywordtype">int</span> ret;

    <span class="comment">/* A warning to programmers who start their own projekt from here. */</span>
    <span class="keywordflow">if</span> (<span class="keyword">sizeof</span>(off_t) != 8) {
         fprintf(stderr,
       <span class="stringliteral">&quot;\nFATAL: Compile time misconfiguration. off_t is not 64 bit.\n\n&quot;</span>);
         exit(39);
    }

    ret = <a class="code" href="libburner_8c.html#a67980a9cee509cf714f67aa96a47c75d" title="Converts command line arguments into above setup parameters.">libburner_setup</a>(argc, argv);
    <span class="keywordflow">if</span> (ret)
        exit(ret);

    printf(<span class="stringliteral">&quot;Initializing libburnia-project.org ...\n&quot;</span>);
    <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a53b82b88a6ebfa788ace50d890080bc6" title="Initialize the library.">burn_initialize</a>())
        printf(<span class="stringliteral">&quot;Done\n&quot;</span>);
    <span class="keywordflow">else</span> {
        printf(<span class="stringliteral">&quot;FAILED\n&quot;</span>);
        fprintf(stderr,<span class="stringliteral">&quot;\nFATAL: Failed to initialize.\n&quot;</span>);
        exit(33);
    }

    <span class="comment">/* Print messages of severity SORRY or more directly to stderr */</span>
    <a class="code" href="libburn_8h.html#a634106ec331c7b7db40a142c467cfb48" title="Control queueing and stderr printing of messages from libburn.">burn_msgs_set_severities</a>(<span class="stringliteral">&quot;NEVER&quot;</span>, <span class="stringliteral">&quot;SORRY&quot;</span>, <span class="stringliteral">&quot;libburner : &quot;</span>);

    <span class="comment">/* Activate the synchronous signal handler which eventually will try to</span>
<span class="comment">       properly shutdown drive and library on aborting events. */</span>
    <a class="code" href="libburn_8h.html#a47b6e05ca3f53ca00f0ef4103eb5cd18" title="Control built-in signal handling.">burn_set_signal_handling</a>(<span class="stringliteral">&quot;libburner : &quot;</span>, NULL, 0x0);
<span class="comment"></span>
<span class="comment">    /** Note: driveno might change its value in this call */</span>
    ret = <a class="code" href="libburner_8c.html#ab485e1b9ba9572fb7596ffa6d6ff67c7" title="You need to aquire a drive before burning.">libburner_aquire_drive</a>(drive_adr, &amp;driveno);
    <span class="keywordflow">if</span> (ret&lt;=0) {
        fprintf(stderr,<span class="stringliteral">&quot;\nFATAL: Failed to aquire drive.\n&quot;</span>);
        { ret = 34; <span class="keywordflow">goto</span> finish_libburn; }
    }
    <span class="keywordflow">if</span> (ret == 2)
        { ret = 0; <span class="keywordflow">goto</span> release_drive; }
    <span class="keywordflow">if</span> (do_blank) {
        <span class="keywordflow">if</span> (do_blank &gt; 100)
            ret = <a class="code" href="libburner_8c.html#a42f03141c04bc55410fdc8e93c4f0143" title="Formats unformatted DVD-RW to profile 0013h &quot;Restricted Overwrite&quot; which needs no blanking for re-use...">libburner_format</a>(drive_list[driveno].drive);
        <span class="keywordflow">else</span>
            ret = <a class="code" href="libburner_8c.html#a0d4b7dff006b3f1f2aac1acc48ba99df" title="Makes a previously used CD-RW or unformatted DVD-RW ready for thorough re-usal.">libburner_blank_disc</a>(drive_list[driveno].drive,
                            do_blank == 1);
        <span class="keywordflow">if</span> (ret&lt;=0)
            { ret = 36; <span class="keywordflow">goto</span> release_drive; }
    }
    <span class="keywordflow">if</span> (source_adr_count &gt; 0) {
        ret = <a class="code" href="libburner_8c.html#af9c2fc57ed6d8505b22d377daef4914b" title="Brings preformatted track images (ISO 9660, audio, ...) onto media.">libburner_payload</a>(drive_list[driveno].drive,
                source_adr, source_adr_count,
                do_multi, simulate_burn, all_tracks_type);
        <span class="keywordflow">if</span> (ret&lt;=0)
            { ret = 38; <span class="keywordflow">goto</span> release_drive; }
    }
    ret = 0;
release_drive:;
    <span class="keywordflow">if</span> (<a class="code" href="libburner_8c.html#aaee536e445f55d19bfeb431850ec90e4" title="This variable indicates wether the drive is grabbed and must be finally released.">drive_is_grabbed</a>)
        <a class="code" href="libburn_8h.html#a765bba03b9f40c07f159ff9ef7db0e09" title="Release a drive.">burn_drive_release</a>(drive_list[driveno].drive, 0);

finish_libburn:;
    <span class="keywordflow">if</span> (<a class="code" href="libburn_8h.html#a98a208e78cc9126a07d1bceea775f4db">burn_is_aborting</a>(0) &gt; 0) {
        <a class="code" href="libburn_8h.html#aa07803603e8be01157ab6a667c5b5a6e" title="Abort any running drive operation and eventually call burn_finish().">burn_abort</a>(4400, <a class="code" href="libburn_8h.html#ad0fd9f069a3f4beb999942b2ec9e82a9" title="A pacifier function suitable for burn_abort.">burn_abort_pacifier</a>, <span class="stringliteral">&quot;libburner : &quot;</span>);
        fprintf(stderr,<span class="stringliteral">&quot;\nlibburner run aborted\n&quot;</span>);
        exit(1);
    } 
    <span class="comment">/* This app does not bother to know about exact scan state. </span>
<span class="comment">       Better to accept a memory leak here. We are done anyway. */</span>
    <span class="comment">/* burn_drive_info_free(drive_list); */</span>
    <a class="code" href="libburn_8h.html#ab9b933537517c9fda9758a9f2b4af337" title="Shutdown the library.">burn_finish</a>();
    exit(ret);
}


<span class="comment">/*  License and copyright aspects:</span>
<span class="comment"></span>
<span class="comment">This all is provided under GPL.</span>
<span class="comment">Read. Try. Think. Play. Write yourself some code. Be free of my copyright.</span>
<span class="comment"></span>
<span class="comment">Be also invited to study the code of cdrskin/cdrskin.c et al.</span>
<span class="comment"></span>
<span class="comment">History:</span>
<span class="comment">libburner is a compilation of my own contributions to test/burniso.c and</span>
<span class="comment">fresh code which replaced the remaining parts under copyright of</span>
<span class="comment">Derek Foreman.</span>
<span class="comment">My respect and my thanks to Derek for providing me a start back in 2005.</span>
<span class="comment"></span>
<span class="comment">*/</span>

</pre></div> </div></div>
<hr class="footer"/><address class="footer"><small>Generated on Sun May 13 2012 for libburn by&#160;
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.7.4 </small></address>
</body>
</html>