Sophie

Sophie

distrib > * > cooker > x86_64 > by-pkgid > 8092ed20821fac5ed4b1a593fb4ef021 > files > 92

lib64cddb-devel-1.3.2-5.x86_64.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <title>CDDB server access library (libcddb)</title>
    <link href="libcddb.css" rel="stylesheet" type="text/css">
  </head>

  <body>

    <table class="menu">
      <tbody>
        <tr class="menu">
          <td class="menu"><a class="menu" href="index.html">Libcddb home</a></td>
          <td class="menu"><a class="menu"  href="download.html">Download</a></td>
          <td class="menu"><a class="menu"  href="faq.html">FAQ</a></td>
          <td class="menu"><a class="menu"  href="tutorial.html">Tutorial</a></td>
          <td class="menu"><a class="menu"  href="API/index.html">API Documentation</a></td>
          <td class="menu"><a class="menu"  href="links.html">Links</a></td>
          <td class="menu"><a class="menu"  href="contact.html">Contact Info</a></td>
        </tr>
      </tbody>
    </table>

<table class="section1"><tr><td><a name="section1">1 Introduction</a></td><td class="sectionnav"><a href="#section2"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section0"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      This tutorial describes the steps that you, as a developer, have
      to take when using libcddb.  It starts with the creation and
      configuration of the CDDB connection.  Afterwards it explains
      how you can retrieve data from the server and even submit new
      entries.  Finally, it shows you what to do if you do not need
      the connection or any related in-memory structures anymore.
    </p>
    <p>
      Throughout this page there are a lot of direct links to the
      libcddb API reference.  In the tutorial text they are easily
      located because of their different color.  But similar links are
      also present in the example source code.  Every libcddb
      function, structure and definition in those code snippets will
      link directly to the corresponding API page.
    </p>
    <p>
      If you have any questions or remarks about this tutorial, if
      something is not completely clear, if you find any errors or
      broken links, do not hesitate to contact me so I can clarify
      and/or correct the issue.  My coordinates can be found on <a
      href="contact.html">Contact Info</a> page.
    </p>

<table class="section1"><tr><td><a name="section2">2 Coding suggestions</a></td><td class="sectionnav"><a href="#section3"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section1"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      No, I'm not going to bother you with where you place your braces
      and stuff like that.  That's not my problem. &nbsp;:-)&nbsp; But
      what I would like to suggest is that whenever you have to
      retrieve something from a libcddb data structure or when you
      have to change something in such a structure, that you use the
      provided get and set functions for that field.  This is good OO
      practice and it will make your life easier if and when I decide
      to change the implementation of one of those structures.  If you
      want to access something for which there is no getter and or
      setter, then just report it to me and I'll add it.
    </p>
    <p>
      Another thing I would like to mention is that you only have to
      include one header file to use libcddb.  The other header files
      depend on each other and have to be included in the correct
      order for it to work.  So, the following statement is enough:
    </p>
<pre class="example"><code>#include &lt;cddb/cddb.h&gt;
</code></pre>
<table class="section1"><tr><td><a name="section3">3 Working with tracks and discs</a></td><td class="sectionnav"><a href="#section4"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section2"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      Before we start with the sections that explain how you can
      access a CDDB server, we have to explain two important libcddb
      data structures: the track and the disc.  These structures are
      used as parameters and return values in the functions that
      access the server.  The following two section describe how you
      can create, use and destroy these tracks and discs.
    </p>

<table class="section2"><tr><td><a name="section3.1">3.1 Tracks</a></td><td class="sectionnav"><a href="#section3.2"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section3.0"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p class="noindent">
      Creation and destruction of a track can be done as shown below.
    </p>
<pre class="example"><code><a href="API/cddb__track_8h.html#1f656d30547194e5a6d9b75406f6b515">cddb_track_t</a> *track = NULL;

/*<i> create </i>*/
track = <a href="API/cddb__track_8h.html#1ff23780b5f261609d253d5f382a9dbe">cddb_track_new</a>();
if (track == NULL) {
    fprintf(stderr, &quot;out of memory, unable to create track&quot;);
}

/*<i> ... use ... </i>*/

/*<i> destroy </i>*/
<a href="API/cddb__track_8h.html#2e2a6b9d7dede4137355181716e372d5">cddb_track_destroy</a>(track);
</code></pre>    <p>
      Next to the two functions used in this example, there is another
      way to create a new track structure. An existing track can be
      duplicated with <a href="API/cddb__track_8h.html#4f5e232db8905a37e8e21e86d07a3a8b">cddb_track_clone</a>.  This function will make an
      exact copy of the existing track, reserving new blocks of memory
      along the way.  It is used internally by libcddb but can also be
      useful for developers in need of a duplicate of a certain track.
    </p>
    <p>
      A similar function is <a href="API/cddb__track_8h.html#1918ba8826aed51573b9187821c668a1">cddb_track_copy</a>.  It requires two existing
      track structures and will copy data from one to the other.  Note
      that a field that is not present in the source track will not
      cause a reset of the corresponding field in the destination
      track.
    </p>
    <p>
      All the other track functions are getters and setters for the
      data fields of the track.  In this section a description of
      those fields is given.  Examples of how to use these will be
      shown in code snippets throughout the next sections.
    </p>
    <ul>
      <li>
        <b>Number:</b> The number of the track on the disc.
        There is only a getter for this field (<a href="API/cddb__track_8h.html#c56671ac6022cccbb71724cb5116f169">cddb_track_get_number</a>).
        It gets set implicitly when you add the track to a disc
        structure.
      </li>
      <li>
        <b>Frame offset:</b> The frame offset of the track on the
        disc.  This is one of the fields that is used to calculate the
        CDDB disc ID. Both a getter and setter function are available
        (<a href="API/cddb__track_8h.html#ca213caee5c7075ee077c89bea7cbdd2">cddb_track_get_frame_offset</a>, <a href="API/cddb__track_8h.html#1db69a3085ebf75430ccc3f4cca7025c">cddb_track_set_frame_offset</a>).
      </li>
      <li>
        <b>Length:</b> The length of the track in seconds.  You can
        manually set this field (<a href="API/cddb__track_8h.html#f3d9820f75e10322bf1847316fcb3e98">cddb_track_set_length</a>).  Libcddb can
        also calculate it for you (<a href="API/cddb__track_8h.html#ec922bbc2dc375c2c272db133f13e16e">cddb_track_get_length</a>) if certain
        requirements are met: the track has to be part of a disc, all
        tracks on the disc need to have their frame offsets defined
        and the disc length has to be known.  If one of these missing,
        the length can not be calculated and -1 will be returned.
      </li>
      <li>
        <b>Title:</b> The title of the track.  Besides the usual get
        and set functions (<a href="API/cddb__track_8h.html#c0fd2e634bd2594e1dbed53d44b01355">cddb_track_get_title</a>, <a href="API/cddb__track_8h.html#105143caf0f925d39a8672279270fdcf">cddb_track_set_title</a>)
        there is also a function to append a string to an already
        existing title (<a href="API/cddb__track_8h.html#7c12cbe3ba0c2cba52b503d85bedec98">cddb_track_append_title</a>).  This function is
        used internally by libcddb, and I do not directly see any use
        for it by libcddb users, but you never known.
      </li>
      <li>
        <b>Artist name:</b> The artist performing the song on this
        track.  You should not set this field if the track is part of
        a disc and all songs on the disc are performed by the same
        artist.  In other words, this field is only useful for
        compilation CDs.  There is a getter, setter and append
        function for this field (<a href="API/cddb__track_8h.html#06ef335da307c849d57eead1bb059391">cddb_track_get_artist</a>,
        <a href="API/cddb__track_8h.html#78764d0cf156ecaa5e907067e424494e">cddb_track_set_artist</a>, <a href="API/cddb__track_8h.html#a8df7b050e2d76dfc7185430de5dee51">cddb_track_append_artist</a>).  If the
        artist name is not set, the get function will return the disc
        artist if the track is part of a disc.
      </li>
      <li>
        <b>Extra data:</b> This field contains any extra data
        pertaining to the track (e.g. composer, lyrics, ...).  As with
        the title and the artist name, you have a getter, setter and
        append function (<a href="API/cddb__track_8h.html#a09b734d43c50759a707e0d563f88c3d">cddb_track_get_ext_data</a>,
        <a href="API/cddb__track_8h.html#9dfe7e399216d6cbdc8ef44336878ce4">cddb_track_set_ext_data</a>, <a href="API/cddb__track_8h.html#3e6ff99c770637568911b4a1050f19c5">cddb_track_append_ext_data</a>).
      </li>
    </ul>
    <p>
      You might wonder how you could retrieve or calculate the frame
      offsets for the tracks of a CD you possess.  I already tried two
      solutions myself.  The first one is to use the command-line tool
      <a href="http://www.xiph.org/paranoia">cdparanoia</a>.  The
      example below shows how you can query a CD in your CD-ROM drive.
    </p>
<pre class="example"><code>$ cdparanoia -Q
cdparanoia III release 9.8 (March 23, 2001)
(C) 2001 Monty &lt;monty@xiph.org&gt; and Xiphophorus
 
Report bugs to paranoia@xiph.org
http://www.xiph.org/paranoia/
 
 
 
Table of contents (audio tracks only):
track        length               begin        copy pre ch
===========================================================
  1.     2334 [00:31.09]        0 [00:00.00]    OK   no  2
  2.    19054 [04:14.04]     2334 [00:31.09]    OK   no  2
 ...
 15.    16432 [03:39.07]   250987 [55:46.37]    OK   no  2
 16.    15924 [03:32.24]   267419 [59:25.44]    OK   no  2
TOTAL  283343 [62:57.68]    (audio only)
</code></pre>    <p>
      From the <code>begin</code> column you can derive the frame
      offset of the tracks.  The only thing you have to do with these
      values is add two seconds of lead-in.  You can use the libcddb
      <a href="API/cddb__disc_8h.html#b1094dade3bf6305a0961885a9a89f0f">SECONDS_TO_FRAMES</a> macro to convert these two seconds to a frame
      count.  This first solution is useful when you quickly want to
      try out some stuff.
    </p>
    <p>
      The second solution is to use libcdio, a library for accessing
      and controlling a CD-ROM device (see <a
      href="links.html">links</a> page for coordinates).  The example
      program supplied with libcddb uses this library, if installed,
      to access the CD-ROM.  The following code snippet shows how to
      retrieve the frame offset with this library.  For the complete
      code check out the <code>cd_access.c</code> file in the libcddb
      <code>examples</code> directory.
    </p>
<pre class="example"><code>CdIo_t *cdio = (NULL, DRIVER_DEVICE);/*<i> libcdio CD access structure </i>*/
track_t t;                           /*<i> libcdio track number </i>*/
lba_t lba;                           /*<i> libcdio Logical Block Address </i>*/
int frame_offset;                    /*<i> libcddb frame offset </i>*/

t = ...                              /*<i> initialize track t </i>*/
lba = cdio_get_track_lba(cdio, t);
if (lba == CDIO_INVALID_LBA) {
    libcdio_error_exit(&quot;track %d has invalid Logical Block Address&quot;, t);
}
</code></pre>    <p>
      The use of this library is probably more elegant than
      the use of an external program. Especially if you are working
      on some code that is also going to be used by other people.
    </p>
    <p>
      Note: the <code>libcdio_error_exit</code> function is not part
      of the libcdio library, but a macro defined in the example code.
    </p>

<table class="section2"><tr><td><a name="section3.2">3.2 Discs</a></td><td class="sectionnav"><a href="#section3.3"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section3.1"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      The life time of a disc is started and ended with similar
      functions as that of a track (see example below).
    </p>
<pre class="example"><code><a href="API/cddb__disc_8h.html#42efa38614123ddc2bcc8a889443ceda">cddb_disc_t</a> *disc = NULL;

/*<i> create </i>*/
disc = <a href="API/cddb__disc_8h.html#d3f011e11da576beb06fc0873aa769bc">cddb_disc_new</a>();
if (disc == NULL) {
    fprintf(stderr, &quot;out of memory, unable to create disc&quot;);
}

/*<i> ... use ... </i>*/

/*<i> destroy </i>*/
<a href="API/cddb__disc_8h.html#9bf985f08f176b23dffdee7af8440b21">cddb_disc_destroy</a>(disc);
</code></pre>    <p>
      As with tracks, it is also possible to duplicate or copy a disc
      using either <a href="API/cddb__disc_8h.html#f2d40d56a702f692fb6c359d0af83277">cddb_disc_clone</a> or <a href="API/cddb__disc_8h.html#dbd8b7d0ecf569edf10af5e304a86f3d">cddb_disc_copy</a>.  The clone
      function will make a brand new copy of the disc and all of its
      tracks.  The copy function will copy data from the source disc
      to the destination disc.  Existing data fields and tracks will
      be overwritten with the new data and tracks.  If the source disc
      has more tracks than the destination disc, then new tracks will
      be added.
    </p>
    <p>
      
    </p>
    <ul>
      <li>
        <b>CDDB ID:</b> The CDDB disc ID.  Together with the disc
        category explained below, this field uniquely identifies a
        disc in the CDDB database.  This field is calculated using the
        length of the disc and the frame offsets of the individual
        tracks.  You can get and set this field (<a href="API/cddb__disc_8h.html#6a2d71c68dfd943575d43094eb96a43b">cddb_disc_get_discid</a>,
        <a href="API/cddb__disc_8h.html#5c30ddb662dbfc62cc0992aa6898b794">cddb_disc_set_discid</a>).  If you do not know the disc ID but the
        disc length and track offsets are initialized, you can have
        libcddb calculate it for you (<a href="API/cddb__disc_8h.html#b2fa8d342aceba66a116c24dda7a7d61">cddb_disc_calc_discid</a>).
      </li>
      <li>
        <b>CDDB category:</b> The CDDB disc category.  The CDDB
        specification defines a set of eleven possible disc
        categories: <i>data</i>, <i>folk</i>, <i>jazz</i>,
        <i>misc</i>, <i>rock</i>, <i>country</i>, <i>blues</i>,
        <i>newage</i>, <i>reggae</i>, <i>classical</i> and
        <i>soundtrack</i>.  Next to the standard get and set functions
        that use one of the values defined by the <a href="API/cddb__disc_8h.html#ea1998e6495d2f0dfa3b6e45b4fcd50d">cddb_cat_t</a>
        enumeration (<a href="API/cddb__disc_8h.html#6456f3f885f08a54efd1382ccd0408f4">cddb_disc_get_category</a>, <a href="API/cddb__disc_8h.html#fb23b487f2168c0fa75ebf8b7d641b38">cddb_disc_set_category</a>),
        there are two alternative functions that use and return
        strings (<a href="API/cddb__disc_8h.html#b7aa4e8f6be9849f434db3d62bceb5cb">cddb_disc_get_category_str</a>,
        <a href="API/cddb__disc_8h.html#a2af35dfbffa7c8a91c9a5fc36671264">cddb_disc_set_category_str</a>).
      </li>
      <li>
        <b>Music genre:</b> The musical genre of the disc.  As opposed
        to the categories from above, this can be any string
        (<a href="API/cddb__disc_8h.html#091f945e67254eb4fc07082c0fb4c484">cddb_disc_get_genre</a>, <a href="API/cddb__disc_8h.html#35e3e624c4d55d16faf0f7563d965f1f">cddb_disc_set_genre</a>).
      </li>
      <li>
        <b>Length:</b> The disc length in seconds
        (<a href="API/cddb__disc_8h.html#22b7b572663a4ebc3aa605c25601b74b">cddb_disc_get_length</a>, <a href="API/cddb__disc_8h.html#403ea0c84c8075fefa6adfaad8184c8c">cddb_disc_set_length</a>).
      </li>
      <li>
        <b>Year:</b> The year of the disc's release
        (<a href="API/cddb__disc_8h.html#93babf05aaf15b2d933163d8b737586f">cddb_disc_get_year</a>, <a href="API/cddb__disc_8h.html#160b7bade529a2c286f51e57e37e9aae">cddb_disc_set_year</a>).
      </li>
      <li>
        <b>Title:</b> The title of the disc.  As with tracks, for the
        disc title there is also a get, set and append function
        (<a href="API/cddb__disc_8h.html#9d48a38c091fe03197e9fe49b0085b72">cddb_disc_get_title</a>, <a href="API/cddb__disc_8h.html#b0c2032a4f21ad0e61c30583cc1bb941">cddb_disc_set_title</a>,
        <a href="API/cddb__disc_8h.html#0e8654c2dd88aa7df9973553d728c805">cddb_disc_append_title</a>).
      </li>
      <li>
        <b>Artist name:</b> The artist performing the tracks on this
        disc.  If this is a compilation disc with different performers
        for different tracks, set it to "Various" and use the artist
        name field of the individual tracks.  Functions are available
        to get, set and append (<a href="API/cddb__disc_8h.html#9f966d8c5085d0673257a8b05e31e1af">cddb_disc_get_artist</a>,
        <a href="API/cddb__disc_8h.html#f565e51732e48511ce5eb50d4849f09e">cddb_disc_set_artist</a>, <a href="API/cddb__disc_8h.html#37ba4c6c3aa25702e5523dba68169326">cddb_disc_append_artist</a>).
      </li>
      <li>
        <b>Extra data:</b> This field contains any extra data
        pertaining to the disc (e.g. composer, producer, ...).  As
        with the title and the artist name, you have a getter, setter
        and append function (<a href="API/cddb__disc_8h.html#78c6056e55bb22274d6867b7b2db09d7">cddb_disc_get_ext_data</a>,
        <a href="API/cddb__disc_8h.html#ad940b347f5ef58cec2da0fd105ab0b6">cddb_disc_set_ext_data</a>, <a href="API/cddb__disc_8h.html#3f1ec775985eb470dcbe6b07221c4ce0">cddb_disc_append_ext_data</a>).
      </li>
    </ul>

<table class="section2"><tr><td><a name="section3.3">3.3 Tracks on discs</a></td><td class="sectionnav"><a href="#section3.4"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section3.2"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      Now that you have seen tracks and discs, let's combine them and
      put some tracks in a disc structure.  With the current API it is
      only possible to append a new track to the end of an existing
      track list.  On the other hand, there are two methods to iterate
      over the tracks on a disc.  The following example illustrates
      this.
    </p>
<pre class="example"><code><a href="API/cddb__disc_8h.html#42efa38614123ddc2bcc8a889443ceda">cddb_disc_t</a> *disc;
<a href="API/cddb__track_8h.html#1f656d30547194e5a6d9b75406f6b515">cddb_track_t</a> *track, *track1, *track2, *track3;
int i, cnt;

/*<i> ... initialize disc and tracks ... </i>*/

/*<i> add some tracks </i>*/
<a href="API/cddb__disc_8h.html#efcd9b6f9709284955af3f02598ba339">cddb_disc_add_track</a>(disc, track1);
<a href="API/cddb__disc_8h.html#efcd9b6f9709284955af3f02598ba339">cddb_disc_add_track</a>(disc, track2);
<a href="API/cddb__disc_8h.html#efcd9b6f9709284955af3f02598ba339">cddb_disc_add_track</a>(disc, track3);

/*<i> iteration method 1 </i>*/
cnt = <a href="API/cddb__disc_8h.html#53b3f46734570bd853ae9b1689c8529d">cddb_disc_get_track_count</a>(disc);
for (t = 0; t &lt; cnt; t++) {
    track = <a href="API/cddb__disc_8h.html#af9a585d49e308b061a06119f4466f93">cddb_disc_get_track</a>(disc, t);
    if (track != NULL) {

        /*<i> ... use track ... </i>*/

    }
}

/*<i> iteration method 2 </i>*/
track = <a href="API/cddb__disc_8h.html#d77ce7b226c41f297af9270a97a0c5e1">cddb_disc_get_track_first</a>(disc);
while (track != NULL) {

    /*<i> ... use track ...  </i>*/

    track = <a href="API/cddb__disc_8h.html#64792c14e85b0d5419c1d2ed5596843f">cddb_disc_get_track_next</a>(disc);
}
</code></pre>    <p>
      When using the first iteration method you should know that the
      <a href="API/cddb__disc_8h.html#af9a585d49e308b061a06119f4466f93">cddb_disc_get_track</a> function starts counting at zero.  Also note
      that the track number, that you get when calling
      <a href="API/cddb__track_8h.html#c56671ac6022cccbb71724cb5116f169">cddb_track_get_number</a>, starts at one.  The <a href="API/cddb__disc_8h.html#af9a585d49e308b061a06119f4466f93">cddb_disc_get_track</a>
      function is probably more useful when you already know the
      number of the track that you want to retrieve.  It will return
      the actual track if the number is valid, or NULL when it is not.
    </p>
    <p>
      For the second method we first reset the internal iteration
      pointer with <a href="API/cddb__disc_8h.html#d77ce7b226c41f297af9270a97a0c5e1">cddb_disc_get_track_first</a>.  The function also
      returns the first track.  Any subsequent tracks can be retrieved
      with the <a href="API/cddb__disc_8h.html#64792c14e85b0d5419c1d2ed5596843f">cddb_disc_get_track_next</a> function.  This function
      returns the next track in the list or NULL if there are no more
      tracks left.
    </p>

<table class="section1"><tr><td><a name="section4">4 Connection set up</a></td><td class="sectionnav"><a href="#section5"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section3"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      The first thing to do when you want to start using any of the
      libcddb functionality is to create a connection structure.
    </p>
<pre class="example"><code><a href="API/cddb__conn_8h.html#56aabb81a12e2653f737f1fde87285d9">cddb_conn_t</a> *conn = NULL;

conn = <a href="API/cddb__conn_8h.html#207796cf79ed9a83a772cde49f7579e4">cddb_new</a>();
if (conn == NULL) {
    fprintf(stderr, &quot;out of memory, &quot;
                    &quot;unable to create connection structure&quot;);
}
</code></pre>    <p>
      The <a href="API/cddb__conn_8h.html#207796cf79ed9a83a772cde49f7579e4">cddb_new</a> function will return a new <a href="API/cddb__conn_8h.html#56aabb81a12e2653f737f1fde87285d9">cddb_conn_t</a> structure.
      This structure keeps the state of the current connection and
      will have to be passed to most of the other libcddb functions.
      If something goes wrong during the creation of this structure,
      NULL will be returned to signal that error.
    </p>
    <p>
      The structure that is returned will have a set of default
      connection settings.  If you use this connection without
      changing any of these settings:
    </p>
    <ul>
      <li>
        it will connect to the CDDB server at <a
        href="http://freedb.org">freedb.org</a> using the CDDBP
        protocol;
      </li>
      <li>
        caching will be enabled, writing any data that is retrieved to
        a subdirectory of the user's home directory
        (<code>$HOME/.cddbslave</code>);
      </li>
      <li>
        and finally, the user and host names used when connecting to a
        server are 'anonymous' and 'localhost'.
      </li>
    </ul>
    <p>
      These default values can be changed after you have created the
      structure.  The following sections explain how to do this.
    </p>

<table class="section2"><tr><td><a name="section4.1">4.1 Server settings</a></td><td class="sectionnav"><a href="#section4.2"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section4.0"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      The first thing to do when you want to change the server
      settings, is decide how you want to contact the server.  The
      list below describes the three options.
    </p>
    <ul>
      <li>
        <b>CDDBP (default):</b> This is the default setting.  It uses
        a custom protocol to interact with the server.  It has the
        advantage that a single TCP connection can be used to send
        multiple commands.  There is of course the disadvantage that
        this protocol might not work if the user is behind a firewall.
      </li>
      <li>
        <b>HTTP:</b> It is possible to tunnel the CDDB commands in
        ordinary HTTP traffic.  This method has the disadvantage that
        there is more overhead since a new TCP session has to be
        established for every command and there is extra data to be
        parsed (HTTP responses).  But the advantage is that it will
        most likely work from behind a firewall.
      </li>
      <li>
        <b>HTTP proxy:</b> Some network setups only allow web access
        through a firewalled proxy server.  This last option enables
        those users to also connect to the CDDB server through that
        proxy server.  There is also support for proxy authentication
        (currently only BasicAuth).
      </li>
    </ul>
    <p>
      The example below shows the steps you have to take when you want
      to change the server settings for the options described above.
      Of course you only have to make the changes for the option you
      choose.  The example also specifies which settings are required
      with the <code>/*<i> REQ </i>*/</code> comment at the end of those
      lines.  The values that are set for the optional fields are also
      the hard coded defaults used by libcddb.
    </p>
<pre class="example"><code>/*<i> CDDBP settings </i>*/
<a href="API/cddb__conn_8h.html#54641c0dac5234713f1916d8d70d8e8b">cddb_set_server_name</a>(conn, &quot;freedb.org&quot;);
<a href="API/cddb__conn_8h.html#f401470406a0139b0ea78c24960361b1">cddb_set_server_port</a>(conn, 888);

/*<i> HTTP settings </i>*/
<a href="API/cddb__conn_8h.html#7a864e89e1d1eb17b958bdd7ed21d260">cddb_http_enable</a>(conn);                                /*<i> REQ </i>*/
<a href="API/cddb__conn_8h.html#f401470406a0139b0ea78c24960361b1">cddb_set_server_port</a>(conn, 80);                        /*<i> REQ </i>*/
<a href="API/cddb__conn_8h.html#54641c0dac5234713f1916d8d70d8e8b">cddb_set_server_name</a>(conn, &quot;freedb.org&quot;);
<a href="API/cddb__conn_8h.html#149b142eaa370b6032ce997fd0ab387e">cddb_set_http_path_query</a>(conn, &quot;/~cddb/cddb.cgi&quot;);
<a href="API/cddb__conn_8h.html#689e000fc2739c94dcee2c396564d2dd">cddb_set_http_path_submit</a>(conn, &quot;/~cddb/submit.cgi&quot;);

/*<i> HTTP proxy settings </i>*/
<a href="API/cddb__conn_8h.html#8e33685500b1f00f6a6b3216a5d501a0">cddb_http_proxy_enable</a>(conn);                          /*<i> REQ </i>*/
<a href="API/cddb__conn_8h.html#8484ac5eb6a1efee1cb440f1bd9de0f7">cddb_set_http_proxy_server_name</a>(conn, &quot;my.proxy.com&quot;); /*<i> REQ </i>*/
<a href="API/cddb__conn_8h.html#f6cbc387b2c20eae3d122577e80196c3">cddb_set_http_proxy_server_port</a>(conn, 8080);           /*<i> REQ </i>*/
<a href="API/cddb__conn_8h.html#f401470406a0139b0ea78c24960361b1">cddb_set_server_port</a>(conn, 80);                        /*<i> REQ </i>*/
<a href="API/cddb__conn_8h.html#54641c0dac5234713f1916d8d70d8e8b">cddb_set_server_name</a>(conn, &quot;freedb.org&quot;);
<a href="API/cddb__conn_8h.html#149b142eaa370b6032ce997fd0ab387e">cddb_set_http_path_query</a>(conn, &quot;/~cddb/cddb.cgi&quot;);
<a href="API/cddb__conn_8h.html#689e000fc2739c94dcee2c396564d2dd">cddb_set_http_path_submit</a>(conn, &quot;/~cddb/submit.cgi&quot;);
/*<i> option 1: stores cleartext credentials </i>*/
<a href="API/cddb__conn_8h.html#0eb1aed5a60b987b68e35aab6f8a789e">cddb_set_http_proxy_username</a>(conn, &quot;myuser&quot;);
<a href="API/cddb__conn_8h.html#596f6f53c24aa16ba7618cc068c814db">cddb_set_http_proxy_password</a>(conn, &quot;mypassword&quot;);
/*<i> option 2: does not store cleartext credentials </i>*/
<a href="API/cddb__conn_8h.html#aa4a07780a2d4602a9d42b4bd42e284d">cddb_set_http_proxy_credentials</a>(conn, &quot;myuser&quot;, &quot;mypassword&quot;);
</code></pre>    <p>
      As shown in the example the actual location of the CDDB server
      (not proxy server) can be changed with calls to
      <a href="API/cddb__conn_8h.html#54641c0dac5234713f1916d8d70d8e8b">cddb_set_server_name</a> and <a href="API/cddb__conn_8h.html#f401470406a0139b0ea78c24960361b1">cddb_set_server_port</a>.  That first
      function accepts both DNS names and IP addresses.
    </p>
    <p>
      Note that when you enable HTTP, you have to correctly initialize
      the server port.  The <a href="API/cddb__conn_8h.html#7a864e89e1d1eb17b958bdd7ed21d260">cddb_http_enable</a> function will not
      automatically set the server port to 80.  When using an HTTP
      proxy server you have to make sure that you correctly initialize
      both the address of the CDDB server and that of the proxy server
      as shown in the example.
    </p>
    <p>
      All the set functions shown above also have a get counterpart.
      You can consult the API reference for the correct syntax.
    </p>

<table class="section2"><tr><td><a name="section4.2">4.2 Cache settings</a></td><td class="sectionnav"><a href="#section4.3"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section4.1"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      As stated above, the default libcddb cache directory is
      <code>$HOME/.cddbslave</code>.  You can change this directory
      with the <a href="API/cddb__conn_8h.html#4279db07e78685fb1a502bbd6096dbb4">cddb_cache_set_dir</a> function.  It will copy the string
      that is passed to it, so any memory used by that string can be
      freed after the function returns.  This function will also
      expand a '<code>~</code>' as the first character to the contents
      of the <code>$HOME</code> environment variable.  If you want to
      check what the current cache directory is, use the
      <a href="API/cddb__conn_8h.html#0b279d3ee74ce0e7948f25b2176c86fd">cddb_cache_get_dir</a> function.  It returns a reference to a field
      inside the connection structure.  You should not alter this
      string directly but use the set-function.
    </p>
    <p class="noindent">
      Caching can be used in three different modes:
    </p>
    <ul>
      <li>
        <b>Enabled (default):</b> When caching is enabled a query or
        read operation will first check whether the requested data is
        present in the local cache.  If it is, then that data will be
        returned.  If it is not, then the server will be accessed.
        After the data has been read from the server it will be stored
        in the cache.  Any subsequent reads will result in a cache
        hit.  You can enable the cache with <a href="API/cddb__conn_8h.html#cd50c16de3aa51dcdc751d2d280c449a">cddb_cache_enable</a>.
      </li>
      <li>
        <b>Cache only:</b> When using this caching mode, libcddb will
        never contact a remote server.  If the requested data is not
        found in the local cache, an appropriate error code will be
        returned.  Enable this feature with <a href="API/cddb__conn_8h.html#ea8e701c4ebeddc6833186cd46b0d357">cddb_cache_only</a>.
      </li>
      <li>
        <b>Disabled:</b> You can also completely disable the cache.
        Any libcddb command will now always contact the remote server.
        No data will ever be retrieved from the cache or stored in the
        cache.  To disable the cache use <a href="API/cddb__conn_8h.html#b39d8c98dcab69671ecb0c00e880e3a7">cddb_cache_disable</a>.
      </li>
    </ul>
    <p>
      If you want to check what the current caching mode is, you
      should us <a href="API/cddb__conn_8h.html#f51571f2931ec69c8ef6211eaeeff9d7">cddb_cache_mode</a>.  This function will return one of
      three values: <a href="API/cddb__conn_8h.html#264ac059c9a7ba457e4054efc7aaa69b916a7dbc1d2807513a9a0ad10c9b13bc">CACHE_ON</a>, <a href="API/cddb__conn_8h.html#264ac059c9a7ba457e4054efc7aaa69b7ca046cd60ca10f3a4ceca753c217567">CACHE_ONLY</a> or <a href="API/cddb__conn_8h.html#264ac059c9a7ba457e4054efc7aaa69b89ceda9ff7fcc69ea74bfb81c1527512">CACHE_OFF</a>.  Each of these
      values maps to the corresponding mode described above.
    </p>

<table class="section2"><tr><td><a name="section4.3">4.3 Miscellaneous settings</a></td><td class="sectionnav"><a href="#section4.4"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section4.2"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      When contacting a CDDB server the protocol requires you to send
      a user and host name before asking any data from the server.  As
      described above, libcddb will use 'anonymous' and 'localhost' as
      the defaults.  These two values are also used when submitting
      new disc entries to the server.  They will be concatenated to
      form the required e-mail address (user@hostname).  This has to
      be a valid e-mail address for the submit to work correctly.  It
      is not possible to submit a disc entry when the default values
      have not been changed.  You can change both these fields in one
      go with <a href="API/cddb__conn_8h.html#cfcd1cffe82707f325d8e47355a243f9">cddb_set_email_address</a>.
    </p>
    <p>
      Another set of values that are also required by the protocol are
      the client name and version.  By default these are set to
      'libcddb' and the version number of libcddb that you are using.
      It is however possible to change these values to the name and
      version of the program that is using the library.  Use the
      <a href="API/cddb__conn_8h.html#1c1d0afabce7dfd17759e46795c3f637">cddb_set_client</a> function to change these client settings.
    </p>
    <p>
      Finally, the libcddb networking code supports time outs.  This
      means that any function that connects to, reads from and writes
      to a remote CDDB server, will not block indefinitely when there
      is a network problem.  By default any of these actions will
      time-out after ten seconds and return with an error status.  You
      can change this time-out interval with the <a href="API/cddb__conn_8h.html#4c4b3c013eb29951c34d161501eb8ca4">cddb_set_timeout</a>
      function.
    </p>

<table class="section1"><tr><td><a name="section5">5 Querying the database</a></td><td class="sectionnav"><a href="#section6"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section4"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      Unless you know the exact disc ID and category of a certain
      disc--in which case you can skip to the section about reading
      disc details--you will first have to query the database to see
      whether there are any matches for your disc.  A CDDB query can
      return
    </p>
    <ul>
      <li>
        no matches;
      </li>
      <li>
        one exact match;
      </li>
      <li>
        multiple exact matches (same disc present in multiple
        categories); or
      </li>
      <li>
        multiple inexact matches (similar disc present in multiple
        categories).
      </li>
    </ul>
    <p>
      Each match that is found will contain the disc ID and disc
      category for that matching disc.  With these two fields a CDDB
      read command can be executed to get the other disc data.  This
      is discussed below.
    </p>
    <p>
      To perform a query operation you will need a disc structure.
      The disc length has to be initialized in this structure and the
      tracks within need to have their frame offset set.  An
      illustration follows.
    </p>
<pre class="example"><code>static int disc_length = 3822;
static int frame_offsets[11] = {
    150, 28690, 51102, 75910, 102682, 121522,
    149040, 175772, 204387, 231145, 268065
};

<a href="API/cddb__disc_8h.html#42efa38614123ddc2bcc8a889443ceda">cddb_disc_t</a> *disc = NULL;
<a href="API/cddb__track_8h.html#1f656d30547194e5a6d9b75406f6b515">cddb_track_t</a> *track = NULL;
int i, matches;

/*<i> (1) initialize disc and tracks </i>*/
disc = <a href="API/cddb__disc_8h.html#d3f011e11da576beb06fc0873aa769bc">cddb_disc_new</a>();
if (disc == NULL) {
    fprintf(stderr, &quot;out of memory, unable to create disc&quot;);
    exit(-1);
}
<a href="API/cddb__disc_8h.html#403ea0c84c8075fefa6adfaad8184c8c">cddb_disc_set_length</a>(disc, disc_length);
for (i = 0; i &lt; 11; i++) {
    track = <a href="API/cddb__track_8h.html#1ff23780b5f261609d253d5f382a9dbe">cddb_track_new</a>();
    if (track == NULL) {
        fprintf(stderr, &quot;out of memory, unable to create track&quot;);
        exit(-1);
    }
    <a href="API/cddb__track_8h.html#1db69a3085ebf75430ccc3f4cca7025c">cddb_track_set_frame_offset</a>(track, frame_offsets[i]);
    <a href="API/cddb__disc_8h.html#efcd9b6f9709284955af3f02598ba339">cddb_disc_add_track</a>(disc, track);
}

/*<i> (2) execute query command </i>*/
matches = <a href="API/cddb__cmd_8h.html#3be764c9073b53160ed6560d5c25fe03">cddb_query</a>(conn, disc);
if (matches == -1) {
    /*<i> something went wrong, print error </i>*/
    <a href="API/cddb__error_8h.html#7c1307f124ccc494bf9def45985c0225">cddb_error_print</a>(<a href="API/cddb__conn_8h.html#41d1b47b9ad3e64f6fa3e94d7547e6e5">cddb_errno</a>(conn));
    exit(-1);
}

while (matches &gt; 0) {

    /*<i> (3) ... use disc ... </i>*/

    /*<i> (4) get next query result if there is one left </i>*/
    matches--;
    if (matches &gt; 0) {
        if (!<a href="API/cddb__cmd_8h.html#0db3f96efbb125a5ebc11f2074431be5">cddb_query_next</a>(conn, disc)) {
            fprintf(stderr, &quot;query index out of bounds&quot;);
            exit(-1);
        }
    }
}
</code></pre>    <p>
      The example first creates a disc structure, initializes the
      total length of the disc to 3822 seconds and adds eleven tracks
      to it (1).  Then it calls the <a href="API/cddb__cmd_8h.html#3be764c9073b53160ed6560d5c25fe03">cddb_query</a> function (2).  This
      function will recalculate the disc ID of the disc provided to it
      and then query the local cache or the remote server for the
      requested information.  The first disc in the query can now be
      processed (3).  We decrement the match counter and if it has not
      yet reached zero, we retrieve the next match with
      <a href="API/cddb__cmd_8h.html#0db3f96efbb125a5ebc11f2074431be5">cddb_query_next</a> (4).
    </p>

<table class="section1"><tr><td><a name="section6">6 Searching the database</a></td><td class="sectionnav"><a href="#section7"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section5"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      An alternative to querying is searching.  If you do not know the
      frame offsets of the tracks on the disc then querying as
      described above is not possible.  In this case you can still
      search for disc data using a text string.  The results returned
      by the search command are similar to those of the query command.
    </p>
<pre class="example"><code>static char *search_str = &quot;mezzanine&quot;;

<a href="API/cddb__disc_8h.html#42efa38614123ddc2bcc8a889443ceda">cddb_disc_t</a> *disc = NULL;
int i, matches;

/*<i> (1) initialize disc </i>*/
disc = <a href="API/cddb__disc_8h.html#d3f011e11da576beb06fc0873aa769bc">cddb_disc_new</a>();
if (disc == NULL) {
    fprintf(stderr, &quot;out of memory, unable to create disc&quot;);
    exit(-1);
}

/*<i> (2) execute search command </i>*/
matches = <a href="API/cddb__cmd_8h.html#3be764c9073b53160ed6560d5c25fe03">cddb_query</a>(conn, disc, search_str);
if (matches == -1) {
    /*<i> something went wrong, print error </i>*/
    <a href="API/cddb__error_8h.html#7c1307f124ccc494bf9def45985c0225">cddb_error_print</a>(<a href="API/cddb__conn_8h.html#41d1b47b9ad3e64f6fa3e94d7547e6e5">cddb_errno</a>(conn));
    exit(-1);
}

while (matches &gt; 0) {

    /*<i> (3) ... use disc ... </i>*/

    /*<i> (4) get next search result if there is one left </i>*/
    matches--;
    if (matches &gt; 0) {
        if (!<a href="API/cddb__cmd_8h.html#a648bcb583dae3e108a38bb514c24799">cddb_search_next</a>(conn, disc)) {
            fprintf(stderr, &quot;search index out of bounds&quot;);
            exit(-1);
        }
    }
}
</code></pre>    <p>
      Again the example code first creates a disc structure in which
      the results will be returned (1).  Then it calls the <a href="API/cddb__cmd_8h.html#68e5f0a66815266245121aba7e82686e">cddb_search</a>
      function (2).  This function will perform a text search on the
      freedb.org web server.  The first disc in the query can now be
      processed (3).  We decrement the match counter and if it has not
      yet reached zero, we retrieve the next match with
      <a href="API/cddb__cmd_8h.html#a648bcb583dae3e108a38bb514c24799">cddb_search_next</a> (4).
    </p>
    <p>
      By default the text search command will only consider the artist
      name field and the disc title field when searching.  It will
      search in every category for the specified string.  You can
      fine-tune this behaviour as shown in the example below.
    </p>
<pre class="example"><code>unsigned int fields = <a href="API/cddb__conn_8h.html#c3528eb88b27e833f1b239dab018b207596ecb69d2e3480c4b5bad071d758de5">SEARCH_ALL</a>;
unsigned int fields = <a href="API/cddb__conn_8h.html#c3528eb88b27e833f1b239dab018b207f22a7dcf1e5539628c03c3bd305b8e95">SEARCH_ARTIST</a> | <a href="API/cddb__conn_8h.html#c3528eb88b27e833f1b239dab018b207098d21d3074984ecab7951bf3db7abc4">SEARCH_TRACK</a>;

<a href="API/cddb__conn_8h.html#98bcdf45d34339bd3b9bee82e5dc4bc3">cddb_search_set_fields</a>(conn, fields);

unsigned int cats = <a href="API/cddb__conn_8h.html#c3528eb88b27e833f1b239dab018b207596ecb69d2e3480c4b5bad071d758de5">SEARCH_ALL</a>;
unsigned int cats = <a href="API/cddb__conn_8h.html#e1655d536ba835be95af11110a519cb4">SEARCHCAT</a>(<a href="API/cddb__disc_8h.html#ea1998e6495d2f0dfa3b6e45b4fcd50d57a322c8a25ae9a30b77f0fcea838872">CDDB_CAT_ROCK</a>) | <a href="API/cddb__conn_8h.html#e1655d536ba835be95af11110a519cb4">SEARCHCAT</a>(<a href="API/cddb__disc_8h.html#ea1998e6495d2f0dfa3b6e45b4fcd50d0f8ff1f94ad8c134bd34c791772d60e7">CDDB_CAT_MISC</a>);

<a href="API/cddb__conn_8h.html#42926ccaf6269a28e4a8bde07ef7b985">cddb_search_set_categories</a>(conn, cats);
</code></pre>    <p>
      For the configuration of the fields any of the <a href="API/cddb__conn_8h.html#c3528eb88b27e833f1b239dab018b207">cddb_search_t</a>
      values can be used.  When specifying which categories to search
      you can use the <a href="API/cddb__conn_8h.html#c3528eb88b27e833f1b239dab018b207596ecb69d2e3480c4b5bad071d758de5">SEARCH_ALL</a> value or you can specify individual
      categories.  When specifying individual <a href="API/cddb__disc_8h.html#ea1998e6495d2f0dfa3b6e45b4fcd50d">cddb_cat_t</a> categories
      you have to use the <a href="API/cddb__conn_8h.html#e1655d536ba835be95af11110a519cb4">SEARCHCAT</a> macro as shown in the example.
    </p>
    <p>
      NOTE: The query and search commands should not be mixed.  They
      both use the same internal list for storing their results.  When
      starting a new query or search, this list is flushed.
    </p>

<table class="section1"><tr><td><a name="section7">7 Reading disc details</a></td><td class="sectionnav"><a href="#section8"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section6"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      Once you know the category and disc ID of a certain CD, you are
      ready to retrieve the rest of the data from the server (or
      cache).
    </p>
<pre class="example"><code><a href="API/cddb__disc_8h.html#42efa38614123ddc2bcc8a889443ceda">cddb_disc_t</a> *disc = NULL;
int success;

/*<i> (1) initialize disc </i>*/
disc = <a href="API/cddb__disc_8h.html#d3f011e11da576beb06fc0873aa769bc">cddb_disc_new</a>();
if (disc == NULL) {
    fprintf(stderr, &quot;out of memory, unable to create disc&quot;);
    exit(-1);
}
<a href="API/cddb__disc_8h.html#a2af35dfbffa7c8a91c9a5fc36671264">cddb_disc_set_category_str</a>(disc, &quot;misc&quot;);
<a href="API/cddb__disc_8h.html#5c30ddb662dbfc62cc0992aa6898b794">cddb_disc_set_discid</a>(disc, 0x920ef00b);

/*<i> (2) execute read command </i>*/
success = <a href="API/cddb__cmd_8h.html#9920c2ce0ebca2a943f3fe28049b5618">cddb_read</a>(conn, disc);
if (!success) {
    /*<i> something went wrong, print error </i>*/
    <a href="API/cddb__error_8h.html#7c1307f124ccc494bf9def45985c0225">cddb_error_print</a>(<a href="API/cddb__conn_8h.html#41d1b47b9ad3e64f6fa3e94d7547e6e5">cddb_errno</a>(conn));
    exit(-1);
}

/*<i> (3) ... use disc ... </i>*/
</code></pre>    <p>
      After we have created the disc structure we initialize the two
      parameters that are required by the read command: the category
      and the disc ID.  An alternative method for setting the category
      is to use the <a href="API/cddb__disc_8h.html#fb23b487f2168c0fa75ebf8b7d641b38">cddb_disc_set_category</a> function with <a href="API/cddb__disc_8h.html#ea1998e6495d2f0dfa3b6e45b4fcd50d0f8ff1f94ad8c134bd34c791772d60e7">CDDB_CAT_MISC</a>
      as the second parameter.  The only thing left to be done, is
      calling the <a href="API/cddb__cmd_8h.html#9920c2ce0ebca2a943f3fe28049b5618">cddb_read</a> function.  This function will return true
      on success and false on failure.
    </p>

<table class="section1"><tr><td><a name="section8">8 Cleaning up</a></td><td class="sectionnav"><a href="#section9"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section7"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      When you do not need a libcddb connection anymore, you should
      call the <a href="API/cddb__conn_8h.html#6e82c862d1338be57dccd92309149854">cddb_destroy</a> function.  This function will properly
      disconnect from the server (if needed) and free all resources
      that were being used by the connection.
    </p>
    <p>
      As already mentioned in the track and disc section of this
      tutorial you should call <a href="API/cddb__track_8h.html#2e2a6b9d7dede4137355181716e372d5">cddb_track_destroy</a> and
      <a href="API/cddb__disc_8h.html#9bf985f08f176b23dffdee7af8440b21">cddb_disc_destroy</a> for freeing the memory used by those
      structures.
    </p>
    <p>
      If you are completely done with all libcddb functionality you
      should also call the <a href="API/cddb_8h.html#5a002ab61c0a144e140844f8705266de">libcddb_shutdown</a> function.  This function
      will free up any global resources that are being shared by all
      connections.
    </p>

<table class="section1"><tr><td><a name="section9">9 Miscellaneous</a></td><td class="sectionnav"><a href="#section10"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section8"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      This section talks about some details that do not fit in any of
      the section above, but nevertheless they are important enough to
      be mentioned
    </p>

<table class="section2"><tr><td><a name="section9.1">9.1 Error handling</a></td><td class="sectionnav"><a href="#section9.2"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section9.0"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      As with all programs, with libcddb it is also possible that
      something goes wrong.  The connection structure also keeps
      information about the result of the last function that has been
      executed.  If this functioned completed successfully, then no
      other actions have to be taken.  On the other hand most
      functions signal an error condition when something goes wrong.
      To determine whether a return value corresponds to an error you
      will have to consult the API documentation for that function.
    </p>
    <p>
      If something went wrong, then you can retrieve the error code
      with the <a href="API/cddb__conn_8h.html#41d1b47b9ad3e64f6fa3e94d7547e6e5">cddb_errno</a> function.  This function will return one of
      the values defined by the <a href="API/cddb__error_8h.html#b8f3141dff6945177d70de613eff6ddb">cddb_error_t</a> enumeration.  Some other
      error handling functions are provided to turn this error code
      into a more descriptive error message.  As a start you can use
      <a href="API/cddb__error_8h.html#4a5070a84e46c80a551dcc1a2eef765a">cddb_error_str</a> to retrieve a string that describes the error
      condition for a given error code.  Alternatively, it is also
      possible to directly print that string to <code>stderr</code> or
      any other stream with <a href="API/cddb__error_8h.html#7c1307f124ccc494bf9def45985c0225">cddb_error_print</a> and cddb_error
      stream_print respectively.
    </p>

<table class="section2"><tr><td><a name="section9.2">9.2 Logging</a></td><td class="sectionnav"><a href="#section9.3"><img class="sectionimg" src="images/arrow_dn.png"></a>&nbsp<a href="#section9.1"><img class="sectionimg" src="images/arrow_up.png"></a></td></tr></table>
    <p>
      Libcddb has a logging framework that can be customized to your
      needs.  Any log message generated by the library functions can
      be categorized into one of five levels: <i>debug</i>,
      <i>informational</i>, <i>warning</i>, <i>error</i> and
      <i>critical</i> (in order of significance).
    </p>
    <p>
      The default log handler will print out any log messages to the
      standard error stream if it has a log level equal or higher than
      a certain minimum level.  By default this minimum is set to
      <i>warning</i>, but it can be changed with the
      <a href="API/cddb__log_8h.html#840bf4742c82ae63cf61b6bb5032ce81">cddb_log_set_level</a> function.  This function accepts any of the
      log levels from the <a href="API/cddb__log_8h.html#1067c83af78e9da497ae86c8defd39ae">cddb_log_level_t</a> enumeration.  One of these
      levels is <a href="API/cddb__log_8h.html#1067c83af78e9da497ae86c8defd39aeba7ad5e887af04201eb0c9f3f2bed1d9">CDDB_LOG_NONE</a>, which can be used to disable the
      printing of any log messages.
    </p>
    <p>
      You can change the library's default minimum log level by
      providing the <code>--enable-loglevel</code> parameter to the
      <code>configure</code> script when compiling libcddb.
    </p>
    <p>
      If you want to do something else with the log messages instead
      of printing them to <code>stderr</code>, then you can create
      your own log handler and set it with <a href="API/cddb__log_8h.html#18a730cfc28bd8ac7bca95d8cfce0c13">cddb_log_set_handler</a>.  The
      signature of the handler function is defined by the
      <a href="API/cddb__log_8h.html#89950157a9af55e9f71e034775ceaba7">cddb_log_handler_t</a> type.  The example below shows how you can
      write a log handler that writes its messages to a file.
    </p>
<pre class="example"><code>FILE *_logfile;

void log_to_file(<a href="API/cddb__log_8h.html#1067c83af78e9da497ae86c8defd39ae">cddb_log_level_t</a> level, const char *message)
{
    fprintf(_logfile, &quot;(%d) %s&quot;, level, message);
    fflush(_logfile);
}
</code></pre>

    <table class="status">
      <tbody>
        <tr>
          <td id="sflogo">
            <a href="http://sourceforge.net">
              <img src="http://sourceforge.net/sflogo.php?group_id=65237&type=1"
                   width="88" height="31" border="0" alt="SourceForge.net Logo"/>
            </a>
          </td>
          <td id="sflogo">
            <a href="http://sourceforge.net/donate/index.php?group_id=65237">
              <img src="http://images.sourceforge.net/images/project-support.jpg"
                   width="88" height="32" border="0"
                   alt="Support This Project"/>
            </a>
          </td>
          <td>
            <address><a href="mailto:airborne@advalvas.be"></a></address>
            Last modified: Sun Oct 15 14:49:16 CEST 2006

          </td>
        </tr>
      </tbody>
    </table>
  </body>
</html>