packages feed

hpodder-1.1.6: doc/hpodder-manpage.sgml

  <refentry id="hpodder.man">
  <indexterm><primary>hpodder</><secondary>Reference For</></>
  <refentryinfo>
    <address><email>jgoerzen@complete.org</email></address>
    <author><firstname>John</firstname><surname>Goerzen</surname></author>
  </refentryinfo>

  <refmeta>
    <refentrytitle>hpodder</refentrytitle>
    <manvolnum>1</manvolnum>
    <refmiscinfo>John Goerzen</refmiscinfo>
  </refmeta>

  <refnamediv>
    <refname>hpodder</refname>
    <refpurpose>Scan and download podcasts</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
    <cmdsynopsis>
      <command>hpodder</command>
      <arg choice="opt">-d</arg>
      <arg choice="opt"><replaceable>command</replaceable></arg>
      <arg choice="opt"><replaceable>command_args</replaceable></arg>
    </cmdsynopsis>
  </refsynopsisdiv>

  <refsect1 id="hpodder.description">
    <title>Description</title>
    <indexterm><primary>Podcasts</primary></indexterm>
    <indexterm><primary>Podcatcher</primary></indexterm>
    <para>
      Podcasting
      is a method of publishing radio-like programs on the
      Internet.  Through podcasting, almost anyone can produce their
      own audio program, and publish episodes of it as often or as
      rarely as they like.
    </para>

    <para>
      To listen to podcasts, you need a program to download the
      podcast's episodes from the Internet.  Such a program is
      called a podcatcher (or sometimes a podcast aggregator).
      &hpodder; is this program.
    </para>

    <para>
      If you'd like to get going RIGHT NOW, skip on down to the
      Quick Start section.  Otherwise, let's take a look at the
      features of &hpodder;.
    </para>

    <refsect2 id="hpodder.features">
      <title>Feature List</title>
      <itemizedlist>
        <listitem><para>Convenient, easy to learn, and fast command-line
            interface (it's simple to do simple things, and
            advanced things are possible)</para>
        </listitem>

        <listitem><para>Automatic discovery of feed metadata such as title</para>
        </listitem>

        <listitem><para>Full history database for accurate
            prevention of duplicate downloads and tracking of new episodes</para>
        </listitem>

        <listitem><para>Conversion tools to convert your existing
            feed list and history from other applications to
            &hpodder;.  Supported applications and formats include:
            castpodder and ipodder.
          </para>
        </listitem>

        <listitem><para>Most operations can work fully automatically
            across your entire podcast database, or they can work
            manually as well.</para>
        </listitem>

        <listitem><para>Automatic updating of ID3 (v1 and v2) tags
            based on metadata in the podcast itself.  This important
            feature is available through iTunes but is often missed by
            other podcatchers.</para>
        </listitem>

        <listitem><para>&hpodder; operations can be easily scripted
            or scheduled using regular operating system tools.</para>
        </listitem>

        <listitem><para>Fully customizable naming scheme for
            downloaded episodes, including a name collision detection
            and workaround algorithm.</para>
        </listitem>

        <listitem><para>Automatic support for appending .mp3
            extensions to MP3 files that lack it.</para>
        </listitem>

        <listitem><para>Numerous database and history inquiry tools</para>
        </listitem>

        <listitem><para>Small, minimalist footprint</para>
        </listitem>

        <listitem><para>Power users and developers can interact
            directly with the embedded Sqlite3 database used by
            &hpodder;.  The database has a simple schema that is
            developer-friendly.</para>
        </listitem>

        <listitem><para>Support for resuming interrupted downloads
            of podcasts</para>
        </listitem>

        <listitem><para>&hpodder; is SAFE and is designed with data
            integrity in mind from the beginning.  It should be
            exceedingly difficult to lose a podcast episode, even in the
            event of a power failure.
          </para>
        </listitem>

      </itemizedlist>
    </refsect2>

    <refsect2 id="hpodder.mo">
      <title>Method of Operation</title>
      <para>
        The basic pattern of operation with &hpodder; is to set up
        each podcast you want to receive.  Each day (or hour, or
        whatever), &hpodder; will go out and update its database by
        pulling in the latest episode lists from the podcast feed.
        Then, &hpodder; will proceed to download any episodes that
        you haven't already downloaded.  After each episode is
        downloaded, &hpodder; will note that fact so it isn't ever
        downloaded again.
      </para>
      <para>
        Let's look at this in a bit more detail.
      </para>
      <para>
        &hpodder; maintains two tables in a database.  One table
        lists all the podcasts you know about, as well as where the
        podcast's feed is to be downloaded from.  The feed is a file
        that the podcast's author publishes.  It lists all the
        current episodes of the podcast, and some information about
        them.  Data is added to this table with the <command>hpodder
          add</command> command.
      </para>
      <para>
        The second table lists each episode for a given podcast,
        along with the location from which the episode can be
        downloaded and some other information about the episode
        (such as its title).  Information in this table is added by
        <command>hpodder update</command> and updated by
        <command>hpodder download</command> or 
        <command>hpodder catchup</command>.
      </para>
      <para>
        When you first fire up &hpodder;, it will read its
        configuration file from
        <filename>~/.hpodder/hpodder.conf</filename>.
        What happens next depends on the command.
      </para>
      <para>
        For <command>hpodder update</command>, the program will read
        information about all your podcasts.  It will download each
        feed.  Once it has the feed, it will look at each episode
        and compare them to the database.  If a given episode is
        already in the database, it is ignored.  Any new episodes
        are recorded in the database, and set to Pending so they
        will be downloaded on the next download run.
      </para>
      <para>
        For <command>hpodder download</command>, the program will
        read information about all your episodes.  For each episode
        marked Pending, the program will download the episode.  It
        will then update the episode's ID3 tags based on the podcast
        feed.  Finally, it will move the episode in-place
        atomically.  Only after all that has been done will
        &hpodder; mark the episode as Downloaded in the database.
        In this way, no episode is visible to outside tools until it
        is completely downloaded in its final form, so you can
        safely play any visible program in your download directory
        even as downloads are happening.
      </para>
    </refsect2>

  </refsect1>

  <refsect1 id="hpodder.quickstart">
    <title>Quick Start</title>
    <para>
      This section will describe how a first-time &hpodder; user can
      get up and running quickly.  It assumes you already have
      &hpodder; compiled or installed on your system.  If not,
      please follow the instructions in the
      <filename>INSTALL</filename>
      file in the
      source distribution.
    </para>
    <para>
      To get started, simply run <command>hpodder</command> at your
      shell prompt.  &hpodder; will lead you through the first-time
      configuration -- which is only two questions and completely
      self-explanatory!
    </para>
    <para>
      After this, whenever you want to download the latest episodes
      for your podcast, just run <command>hpodder</command> again.
    </para>
    <para>
      At some point, you'll want to add more podcasts to &hpodder;.
      To do that, just run a command such as:
    </para>
    <para><command>hpodder add
        <replaceable>http://www.example.com/feed.xml</replaceable></command></para>
    <para>
      Just replace the example.com URL here with the real URL of the
      feed you want to add.  Then run <command>hpodder
        update</command>.  If the podcast you've just added has a
      whole bunch of episodes, you may not want to download them
      all.  In that case, run <command>hpodder catchup
        <replaceable>id</replaceable></command>, where
      <replaceable>id</replaceable> is the podcast number that
      &hpodder; gave your new podcast when you added it.
    </para>
    <para>
      Again, from here on, you can just run
      <command>hpodder</command> to download all your new episodes.
    </para>
  </refsect1>

  <refsect1 id="hpodder.options">
    <indexterm><primary>Options (command-line)</primary></indexterm>
    <title>Options</title>
    <para>
      &hpodder; always is invoked with the name of a specific
      operation, such as <option>update</option> or
      <option>add</option>.  In &hpodder;, these operations are
      called <emphasis>commands</emphasis>.  Each command has its
      own options, which are given after the command on the
      &hpodder; command line.  A full summary of each command's
      options is given later in this manual.
    </para>
    
    <para>
      You may obtain a list of all commands with <command>hpodder
        lscommands</command>.  Help is available for any individual
      command with <command>hpodder <replaceable>command</replaceable>
        --help</command>.  Global help is available with
      <command>hpodder --help</command>.
    </para>
    <refsect2 id="hpodder.options.global">
      <title>Global Option</title>
      <para>
        This option may be specified <emphasis>before</emphasis> any
        command.
      </para>
      <variablelist>
        <varlistentry><term>-d</term><term>--debug</term>
          <listitem><para>
              Enables debugging output.  This verbose output helps you
              learn what &hpodder; is doing every step of the way and
              diagnose any problems you may encounter.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
    </refsect2>

  </refsect1>

  <refsect1 id="hpodder.commands">
    <indexterm><primary>Commands</primary></indexterm>
    <title>Commands in hpodder</title>
    <para>
      &hpodder; has many different commands.  If you do not specify a
      command, the <command>fetch</command> command is automatically
      selected for you.  This section will discuss each command in
      detail.  Note that all commands are case-sensitive and should be
      <emphasis>given in lowercase</emphasis>.
    </para>
    <para>
      All commands support the command <option>--help</option>.  Running
      <command>hpodder <replaceable>command</replaceable>
      --help</command> will display information about the command and
      its options.  Since all commands support this, it won't be
      explicitly listed for each command below.
    </para>

    <refsect2 id="hpodder.commands.add">
      <indexterm><primary>Commands</primary><secondary>add</></>
      <indexterm><primary>Podcasts</><secondary>Adding to hpodder</></>
      <title>add</title>
      <cmdsynopsis>
        <command>hpodder add</command>
        <arg choice="plain"><replaceable>URL</replaceable></arg>
      </cmdsynopsis>
      <para>
        This command is used to add a new podcast to &hpodder;.  You
        can must provide the URL (link) to the podcast you want to add
        to this command.  For example:
      </para>
      <para><command>hpodder add
      http://soundofhistory.complete.org/files_soh/podcast.xml</command></para>
      <para>
        A podcast can be later removed with <command>hpodder
        rm</command>.  You can adjust its URL later with
        <command>hpodder mv</command>.
      </para>
    </refsect2>
    
    <refsect2 id="hpodder.commands.catchup">
      <indexterm><primary>Commands</><secondary>catchup</></>
      <indexterm><primary>Episodes</><secondary>Skipping</></>
      <title>catchup</title>
      <cmdsynopsis>
        <command>hpodder catchup</command>
        <arg choice="opt">-n <replaceable>number</replaceable></arg>
        &arg.castid;
      </cmdsynopsis>
      <para>
        Running <command>catchup</command> will cause &hpodder; to
        mark all but the most recent episodes as Skipped.  This will
        prevent &hpodder; from automatically downloading such
        episodes.
      </para>
      <variablelist>
        <varlistentry><term>-n <replaceable>NUM</replaceable></term>
          <term>--number-eps=<replaceable>NUM</replaceable></term>
          <listitem><para>
              By default, only the single most recent episode is exempted
              from being "caught up".  If you want to exclude more
              episodes from being "caught up" -- and thus allow more
              to be downloaded -- use this option to allow more
              episodes to remain downloadable.
            </para>
          </listitem>
        </varlistentry>

        &var.castid;
      </variablelist>
    </refsect2>

    <refsect2 id="hpodder.commands.disable">
      <indexterm><primary>Commands</><secondary>disable</></>
      <title>disable</title>
      <cmdsynopsis>
        <command>hpodder disable</command>
        <arg choice="plain" rep="repeat">castid</>
      </cmdsynopsis>
      <para>
        This command will flag podcasts as disabled.  Podcasts flagged
        disabled will be skipped during an <command>update</command>,
        <command>download</command>, or <command>fetch</command>.
        They will still participate with all other commands.
        <command>hpodder lscasts</command> will notify you of which
        podcasts are disabled.
      </para>
      <para>
        This can be useful if you want to stop following a podcast for
        awhile, but think you may want to come back to it in the
        future.  The podcast URL and your download history will remain
        in the &hpodder; database, unlike with <command>hpodder
        rm</command>.
      </para>
      <para>
        Disabled podcasts can be re-enabled with <command>hpodder
        enable</command>.
      </para>
      <para>
        One or more podcast IDs are required; see the section below on
        specifying podcast IDs for more details.
      </para>
    </refsect2>

    <refsect2 id="hpodder.commands.download">
      <indexterm><primary>Commands</><secondary>download</></>
      <indexterm><primary>Episodes</><secondary>Downloading</></>
      <title>download</title>
      <cmdsynopsis>
        <command>hpodder download</command>
        &arg.castid;
      </cmdsynopsis>
      <para>
        The <command>download</command> command is used to actually
        perform the download of podcasts to your system.  By default,
        <command>download</command> will download all available
        episodes.  You can, however, specify only certain podcasts to
        process; if you do, all available episodes for only those
        podcasts will be downloaded.
      </para>
      <variablelist>&var.castid;</variablelist>
    </refsect2>

    <refsect2 id="hpodder.commands.enable">
      <indexterm><primary>Commands</><secondary>enable</></>
      <title>enable</title>
      <cmdsynopsis>
        <command>hpodder enable</command>
        <arg choice="plain" rep="repeat">castid</>
      </cmdsynopsis>
      <para>
        This command will flag podcasts as enabled.  This is the
        default state.  See <command>hpodder disable</command> for
        information on manually disabling podcasts and what it means
        to be disabled.
      </para>
      <para>
        One or more podcast IDs are required; see the section below on
        specifying podcast IDs for more details.
      </para>
    </refsect2>

    <refsect2 id="hpodder.commands.fetch">
      <indexterm><primary>Commands</><secondary>fetch</></>
      <indexterm><primary>Podcasts</><secondary>Updating</></>
      <indexterm><primary>Episodes</><secondary>Downloading</></>
      <title>fetch</title>
      <cmdsynopsis><command>hpodder fetch</command>&arg.castid;</cmdsynopsis>
      <para>
        The <command>fetch</command> is the main worker command for
        &hpodder;.  It is simply equivolent to <command>hpodder
        update</command> followed by <command>hpodder
        download</command>.  That is, it will scan all podcasts for
        new episodes, then download any pending episodes.
      </para>
      <para>
        This command is the default command if no command is given on
        the &hpodder; command line.
      </para>
      <para>
        As a special feature, the first time that
        <command>fetch</command> is invoked, it will execute the new
        user setup procedure.
      </para>
      <variablelist>&var.castid;</variablelist>
    </refsect2>

    <refsect2 id="hpodder.commands.import-ipodder">
      <indexterm><primary>Commands</><secondary>import-ipodder</></>
      <indexterm><primary>ipodder</><secondary>Converting From</></>
      <title>import-ipodder</title>
      <cmdsynopsis><command>hpodder import-ipodder</command>
        <arg
      choice="opt">--from=<replaceable>PATH</replaceable></arg></cmdsynopsis>
      <para>
        With this command, &hpodder; can import both your podcast list
        and your download history from ipodder or CastPodder.
        &hpodder; will import all podcasts referenced there, with the
        exception that any podcasts that are already in &hpodder;'s
        database will be entirely untouched.
      </para>
      <variablelist>
        <varlistentry><term>--from=<replaceable>PATH</replaceable></term>
          <listitem><para>By default, &hpodder; will look for the ipodder
            database in the <filename>.ipodder</filename> directory in
            the user's home directory.  This may not always be correct:
            for instance, on non-Unix platforms or when using
            CastPodder, this directory will be different.  With this
            option, you can tell &hpodder; where to find the
            ipodder/CastPodder database.
            </para></listitem>
        </varlistentry>
      </variablelist>
    </refsect2>

    <refsect2 id="hpodder.commands.lscasts">
      <indexterm><primary>Commands</><secondary>lscasts</></>
      <indexterm><primary>Podcasts</><secondary>Listing</></>
      <title>lscasts</title>
      <cmdsynopsis><command>hpodder lscasts</command>
        <arg choice="opt">-l</arg></cmdsynopsis>
      <para>
        This command will display all podcasts that are configured
        within &hpodder;.  For each podcast, you will see the podcast
        ID, the number of pending downloads, the total number of
        episodes ever seen by &hpodder;, and the title of the podcast.
      </para>
      <variablelist>
        <varlistentry><term>-l</term>
          <listitem><para>
              If you add the <option>-l</option> option, then
          <command>lscasts</command> will also display the feed URL
          for each podcast.
            </para></listitem>
        </varlistentry>
      </variablelist>
    </refsect2>

    <refsect2 id="hpodder.commands.lscommands">
      <indexterm><primary>Commands</><secondary>lscommands</></>
      <title>lscommands</title>
      <cmdsynopsis><command>hpodder lscommands</command></cmdsynopsis>
      <para>
        This command will display a list of all available &hpodder;
        commands along with a brief description of each.
      </para>
    </refsect2>

    <refsect2 id="hpodder.commands.lsepisodes">
      <indexterm><primary>Commands</><secondary>lsepisodes</></>
      <indexterm><primary>Commands</><secondary>lseps</></>
      <indexterm><primary>Episodes</><secondary>Listing</></>
      <title>lsepisodes / lseps</title>
      <cmdsynopsis><command>hpodder lsepisodes</command>
        <arg choice="opt">-l</arg>&arg.castid;
      </cmdsynopsis>
      <cmdsynopsis><command>hpodder lseps</command>
        <arg choice="opt">-l</arg>&arg.castid;
      </cmdsynopsis>
      <para>
        The <command>lsepisodes</command> command will display a list
        of every episode known to &hpodder;.  The output will include
        the ID of the podcast to which the episode belongs, the
        episode ID, the status of the episode, and the title of the
        episode.
      </para>
      <para>
        <command>lseps</command> is simply an alias for
        <command>lsepisodes</command> and performs in the same manner.
      </para>
      <variablelist>
        <varlistentry><term>-l</term>
          <listitem><para>
              If you add the <option>-l</option> option, then
          <command>lsepisodes</command> includes the download URL for
          each episode in its output.</para></listitem></varlistentry>
        &var.castid;
      </variablelist>
    </refsect2>
    
    <refsect2 id="hpodder.commands.rm">
      <indexterm><primary>Commands</><secondary>rm</></>
      <indexterm><primary>Podcasts</><secondary>Removing</></>
      <title>rm</title>
      <cmdsynopsis><command>hpodder rm</command>
        <arg choice="plain" rep="repeat">castid</>
      </cmdsynopsis>
      <para>
        This command will remove all knowledge about a given podcast
        from hpodder, including all entries about that podcast in the
        episode database.
      </para>
      <para>
        One or more podcast IDs are required; see the section below on
        specifying podcast IDs for more details.  Unlike most other
        &hpodder; commands that accept an empty podcast ID list to
        mean all podcasts, <command>rm</command> does not because of
        the destructive potential of such a request.
      </para>
    </refsect2>

    <refsect2 id="hpodder.commands.setstatus">
      <indexterm><primary>Commands</><secondary>setstatus</></>
      <indexterm><primary>Episodes</><secondary>Status Flags</><tertiary>Updating</></>
      <title>setstatus</title>
      <cmdsynopsis><command>hpodder setstatus</command>
        <arg choice="plain">--castid=<replaceable>ID</replaceable></arg>
        <arg choice="plain">--status=<replaceable>STATUS</replaceable></arg>
        <arg choice="plain" rep="repeat">epid</arg></cmdsynopsis>
      <para>
        The <command>setstatus</command> command is used to manually
        adjust the status flags on individual episodes.  You can use
        it to flag individual episodes for downloading (or not).
      </para>
      <para>
        You must specify at least one episode ID.  <emphasis>Note that
        the plain IDs given to this command are episode IDs</emphasis>, and not
        podcast IDs like other commands.
      </para>
      <para>
        Statuses are case-sensitive and must be given with a leading
        uppercase letter and trailing lowercase letters.  Available
        status are given later in this manual.
      </para>
        
    </refsect2>

    <refsect2 id="hpodder.commands.settitle">
      <indexterm><primary>Commands</><secondary>settitle</></>
      <indexterm><primary>Podcasts</><secondary>Title</></>
      <title>settitle</title>
      <cmdsynopsis><command>hpodder settitle</command>
        <arg choice="plain">--castid=<replaceable>ID</replaceable></arg>
        <arg choice="plain">--title=<replaceable>TITLE</replaceable></arg>
      </cmdsynopsis>
      <para>
        The <command>settitle</command> is used to manually set the
        title of a given podcast.  Normally, &hpodder; will
        automatically get the title from the podcast's XML feed.
        Sometimes the XML feed for the podcast may not provide a
        useful title.  In those situations, you can use
        <command>settitle</command> to manually override the title.
      </para>
      <para>
        Please note that if you want to set the title to a name that
        contains spaces, you will need to quote it for the shell.
      </para>
    </refsect2>


    <refsect2 id="hpodder.commands.update">
      <indexterm><primary>Commands</><secondary>update</></>
      <indexterm><primary>Podcasts</><secondary>Updating</></>
      <title>update</title>
      <cmdsynopsis><command>hpodder update</command>&arg.castid;</>
      <para>
        The update command will cause &hpodder; to look at each
        podcast feed.  It will download the latest copy of the feed
        and compare the episodes mentioned in the feed to its internal
        database of episodes.  For any episode mentioned in the feed
        that is not already in the internal database of episodes,
        &hpodder; will add it to its database and set its status to
        Pending.
      </para>
      <variablelist>&var.castid;</variablelist>
    </refsect2>
        
  </refsect1>

  
  <refsect1 id="hpodder.castids">
    <title>Specifying podcast IDs</title>
    <indexterm><primary>Podcasts</><secondary>IDs</></>
    <para>
      Each podcast in &hpodder; gets a numeric ID.  This ID is
      automatically assigned by &hpodder; and is not changable.  The
      ID is given out when a podcast is added with the
      <command>add</command> command, or with the
      <command>lscasts</command> or <command>lsepisodes</command>
      commands.
    </para>
    <para>
      The ID is designed as a constant way to refer to a particular
      podcast.  A podcast's title may change, or even its feed URL,
      but the ID of a podcast will never change.  It also is short and
      easy to type on the command line.
    </para>
    <para>
      Several commands can take a list of podcast IDs.  If no IDs are
      given, the commands will default to operating on all podcasts.
      One or more IDs can be given, separated by spaces.  If IDs are
      given, then the commands will operate only on the podcasts with
      the given IDs.
    </para>
    <para>
      The special keyword <option>all</option> may be given, which
      tells the system to operate on all podcasts.  This yields the
      same result as giving no IDs at all.
    </para>
  </refsect1>

  <refsect1 id="hpodder.statuses">
    <indexterm><primary>Episodes</><secondary>Status Flags</></>
    <title>Status Flags in hpodder</title>
    <para>
      Several places in this manual, you've seen &hpodder; statuses
      mentioned.  Each episode in &hpodder; has an associated status.
      The statuses are:
    </para>
    <variablelist>
      <varlistentry><term>Pending</term>
        <listitem><para>The given episode is ready to
        download</para></listitem>
      </varlistentry>
      <varlistentry><term>Downloaded</term>
        <listitem><para>The given episode has already been
        downloaded by &hpodder;</para></listitem>
      </varlistentry>
      <varlistentry><term>Error</term>
        <listitem><para>An error occured while downloading this
        episode.  It will not be downloaded again unless the flag is
        set back to Pending.</para></listitem>
      </varlistentry>
      <varlistentry><term>Skipped</term>
        <listitem><para>The user has requested that this episode not
        be downloaded.  Commands such as <command>catchup</command> or
            <command>import-ipodder</command> could cause this.
          </para></listitem>
      </varlistentry>
    </variablelist>
  </refsect1>

  <refsect1 id="hpodder.error">
    <indexterm><primary>Errors</></>
    <title>Automatic Error Handling</title>
    <para>
      For whatever reason, podcast feeds or individual episodes sometimes
      fail to download.  The reasons for this range from the podcast being
      taken down by its author to the network being disconnected from the
      local computer.
    </para>
    <para>
      People that track many podcasts over a long time will probably find it
      annoying to have &hpodder; attempt to download invalid feeds or
      episodes over and over again.  For that reason, &hpodder; 1.0.0
      introduced automatic error handling.
    </para>
    <para>
      Once a podcast feed or episode has failed at least 15 times, 
      it's been at least 21 days since the first download attempt (episodes)
      or last update (feeds), &hpodder; will automatically mark the item to
      be skipped in future runs.  For podcast feeds, &hpodder; disabled the
      podcast; this status will appear in <command>hpodder lscasts</>.
      For episodes, &hpodder; sets the status to Error; this will appear
      in <command>hpodder lseps</>.  Both can be changed later, with
      <command>hpodder enable</> or <command>hpodder setstatus</>,
      respectively.
    </para>
    <para>
      The default minimums of 15 attempts and 21 days may be adjusted in
      the &hpodder; configuration file, either globally or on a per-podcast
      basis.
    </para>
    <para>
      If you wish to disable checking entirely, you can put lines such as
      <literal>epfaildays = 123456789</literal> and
      <literal>podcastfaildays = 123456789</literal> in your <literal>DEFAULT</>
      section in <filename>~/.hpodder/hpodder.conf</>.  Of course, if you
      have podcasts that still fail after 338,237 years, you could be in
      trouble.
    </para>
  </refsect1>

  <refsect1 id="hpodder.config">
    <indexterm><primary>Configuration File</><secondary>hpodder</></>
    <title>hpodder Configuration File</title>
    <para>
      &hpodder; has a configuration file in which you can set various
      options.  This file normally lives under
      <filename>~/.hpodder/hpodder.conf</filename>.
    </para>
    <para>
      The configuration file has multiple sections.  Each section has
      a name and is introduced with the name in brackets.  Each
      section has one or more options.
    </para>
    <para>
      The section named DEFAULT is special in that it provides
      defaults that will be used whenever an option can't be found
      under a different section.
    </para>
    <para>
      Let's start by looking at an example file, and then proceed to
      examine all the options that are available.
    </para>
    <programlisting><![CDATA[
[DEFAULT]

; Most podcasts are downloaded to here
downloaddir = /home/jgoerzen/podcasts

namingpatt = %(safecasttitle)s/%(safefilename)s

; Don't disable a podcast due to errors unless it's been at least 20
; days since the last (or first) attempt
podcastfaildays = 20

[general]

; The following line tells hpodder that
; you have already gone through the intro.
showintro = no

maxthreads = 2
progressinterval = 1

[31]
; Store this particular podcast somewhere else
downloaddir = /nfs/remote/podcasts

; And we don't care as much about disabling it
podcastfaildays = 5
]]></programlisting>
    <para>
      In this example, you saw some "general" options, such as
      <option>showintro</option>.  There are two other sections
      represented: <option>31</option> and <option>DEFAULT</option>.
    </para>
    <para>
      Whenever &hpodder; looks for information about a particular
      podcast, it first checks to see if it can find that option in a
      section for that podcast.  If not, it checks the
      <option>DEFAULT</option> section.  If it still doesn't find an
      answer, it consults its built-in defaults.
    </para>
    <para>
      In this example, all podcasts share the same naming scheme.  All
      podcasts except podcast 31 are downloaded to the same place.
      That podcast goes elsewhere because its
      <option>downloaddir</option> overrides the default.
    </para>
    <refsect2 id="hpodder.config.general">
      <title>General Options</title>
      <para>These are specified in the <option>general</option>
        section.
      </para>
      <variablelist>
        <varlistentry><term>maxthreads</term>
          <listitem><para>The maximum number of simultaneous download
              threads that will be active at any given time.
              &hpodder; can download multiple files at once, and this
              options says how many it can download simultaneously.
              It defaults to 2.
            </para></listitem>
        </varlistentry>
        <varlistentry><term>progressinterval</term>
          <listitem><para>How frequently to update the status bar on
          the screen, in seconds.  It defaults to 1, which will update
          the status every second.  Raise it if you are running
          &hpodder; over a very low-bandwidth link and are concerned
          about flooding it with status updates.</para></listitem>
        </varlistentry>
        <varlistentry><term>showintro</term>
          <listitem><para>The first time you run
              <command>fetch</command>, &hpodder; automatically writes a
              configuration file for you that sets this option to
              <option>no</option>.  This prevents you from having to
              do the new user intro more than once.
            </para></listitem>
        </varlistentry>
      </variablelist>
    </refsect2>              

    <refsect2 id="hpodder.config.podcast">
      <title>Per-Podcast Options</title>
      <para>
        These options may be specified in <option>DEFAULT</option> or
        in a per-podcast section.  If placed in
        <option>DEFAULT</option>, they will apply to all podcasts
        unless overridden.
      </para>
      <refsect3 id="hpodder.config.podcast.basic">
        <title>Basic Per-Podcast Options</title>
      <variablelist>
        <varlistentry><term>downloaddir</term>
          <listitem><para>The main directory into which all podcasts
              should be stored.  It will be created by &hpodder; when
              necessary if it does not already exist.  The default is
            <filename>~/podcasts</filename></para></listitem>
        </varlistentry>
        <varlistentry><term>epfailattempts</term>
          <listitem><para>
            The minimum number of attempts to download this episode before
            the episode will be considered to be marked Error.  Default is
            15.
          </para></listitem>
        </varlistentry>
        <varlistentry><term>epfaildays</term>
          <listitem><para>
            The minimum number of days that must have elapsed between the
            first attempt to download the episode and the present time before
            the episode will be considered to be marked Error.  Default is
            21.
            </para>
            </listitem>
            </varlistentry>
        <varlistentry><term>namingpatt</term>
          <listitem><para>How to name downloaded files.  This pattern
          is relative to the <option>downloaddir</option>.  The
          default is
          <filename>%(safecasttitle)s/%(safefilename)s</filename>
            </para>
            <para>
              This option will be provided with several replaceable
              tokens.  Tokens have the form
              <option>%(<replaceable>tokname</replaceable>)s</option>.
              That is, the percent sign, the token name in
              perenthesis, and then an "s" character.  The tokens made
              available for this option are:
            </para>
            <variablelist>
              <varlistentry><term>castid</term>
                <listitem><para>The numeric ID for this
                podcast</para>
                </listitem></varlistentry>
              
              <varlistentry><term>epid</term>
                <listitem><para>The numeric ID for this
                episode
                  </para>
                </listitem>
              </varlistentry>

                <varlistentry><term>safecasttitle</term>
                  <listitem><para>The title of the podcast, as specified
                      in the feed.  Special characters, such as spaces or
                      exclamation marks, are converted to
                      underscores.</para></listitem>
                </varlistentry>

                <varlistentry><term>safeeptitle</term>
                  <listitem><para>The title of this episode, as
                      specified in the podcast's feed, with special
                      characters converted to underscores.
                    </para></listitem></varlistentry>

                <varlistentry><term>safefilename</term>
                  <listitem><para>The component from the URL for this
                      episode after the last slash in the URL, with special
                      characters converted to underscores.
                    </para>
                  </listitem>
                </varlistentry>
              </variablelist>
            </listitem>
          </varlistentry>
          <varlistentry><term>podcastfailattempts</term>
            <listitem><para>
                The minimum number of attempts to download this podcast before
                the episode will be considered to be marked disabled.  Default is
                15.
              </para></listitem>
          </varlistentry>
          <varlistentry><term>podcastfaildays</term>
            <listitem><para>
                The minimum number of days that must have elapsed between the
                last successful download of the podcast's feed
                and the present time before
                the podcast will be considered to be marked disabled.  Default is
                21.
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
      </refsect3>
      <refsect3 id="hpodder.config.podcast.processing">
        <title>Per-Podcast Command Options</title>
        <para>
          These are external commands that will be run in certain
          situations.  For each of the commands, several environment
          variables are set.  These variables are not pre-sanitized
          and may contain whitespace or special characters.  
          <emphasis>Extreme
          caution must be exercized to properly quote these variables
          when using them in shell commands or scripts.</emphasis>
          The following
          environment variables are set:
        </para>
        <variablelist>
          <varlistentry><term>CASTID</term>
            <listitem><para>The numeric ID for this podcast</para>
            </listitem>
          </varlistentry>
          
          <varlistentry><term>CASTTITLE</term>
            <listitem><para>The title of the podcast,
            verbatim</para></listitem>
          </varlistentry>

          <varlistentry><term>EPFILENAME</term>
            <listitem><para>The on-disk filename where this episode
            has been stored</para></listitem></varlistentry>

          <varlistentry><term>EPID</term>
            <listitem><para>The numeric epidose ID for this
            episode</para>
            </listitem>
          </varlistentry>

          <varlistentry><term>EPTITLE</term>
            <listitem><para>The title of this episode, as specified in
            the podcast's feed.</para>
            </listitem>
          </varlistentry>

          <varlistentry><term>EPURL</term>
            <listitem><para>The URL of this episode.</para></listitem>
          </varlistentry>

          <varlistentry><term>FEEDURL</term>
            <listitem><para>The URL of the podcast's
            feed.</para></listitem>
          </varlistentry>


          <varlistentry><term>SAFECASTTITLE</term>
            <listitem><para>The title of the podcast, as specified in
            the feed.  Special characters, such as spaces or
            exclamation marks, are converted to
            underscores.</para></listitem>
          </varlistentry>

          <varlistentry><term>SAFEEPTITLE</term>
            <listitem><para>The title of this episode, as specified in
            the podcast's feed, with special characters converted to
            underscores.
              </para></listitem></varlistentry>
        </variablelist>
        <para>
          Here are the supported commands:
        </para>
        <variablelist>
          <varlistentry><term>gettypecommand</term>
            <listitem><para>This command is intended to analyze the
                content of the file and return the true MIME type of the
                file, based on the on-disk content.  If this command exits
                with an error, the MIME type given in the podcast feed will
                be used.  If you want to always use the MIME type in the
                podcast feed, you can set this to
                <literal>/bin/false</literal> or the empty string.
              </para>
              <para>The default value is: <literal>file -b -i "${EPFILENAME}"</literal>
              </para>
              <para>
                It is expected that this program will write its result
                to standard output.  The first token of the output is
                taken to be the MIME type.  The remainder will be
                discarded.  For instance, for the output
                <literal>text/x-pascal; charset=us-ascii</literal>,
                the type will be taken to be
                <literal>text/x-pascal</literal>.  If the program
                exits with a nonzero exit code, its output will not be used.
              </para>
            </listitem>
          </varlistentry>

          <varlistentry><term>postproccommand</term>
            <listitem><para>This command provides a user-configurable
                post-processing hook for downloaded podcasts.  It is only
                invoked on files whose type matches the
                <option>postproctypes</option> list.  This command is the
                very last step in the downloading process.
              </para>
              <para>
                The default value adds ID3 tags to MP3 files.  It is:
                <literal>mid3v2 -T "${EPID}" -A "${CASTTITLE}" -t "${EPTITLE}" --WOAF
                  "${EPURL}" --WOAS "${FEEDURL}" "${EPFILENAME}"</literal>
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
      </refsect3>

      <refsect3 id="hpodder.config.podcast.types">
        <title>Per-Podcast Type Processing Lists</title>
        <para>
          These options govern what types of files are processed in
          different ways.  The types used here are MIME types.  They
          will be the actual type determined by
          <option>gettypecommand</option>, or if that command is
          unable to determine a useful type, the MIME type given by
          the podcast's RSS feed.  Items in these lists are to be
          separated by commas.
        </para>
        <variablelist>
          <varlistentry><term>postproctypes</term>
            <listitem>
              <para>
                This is the comma-separated list of MIME types on
                which <option>postproccommand</option> will operate.
                The special single token <literal>ALL</literal> means
                to operate on all types.  To disable post-processing
                entirely, you can set this to the empty string.
                The default is: <literal>audio/mpeg, audio/mp3,
                x-audio/mp3</literal>
              </para></listitem></varlistentry>

          <varlistentry><term>renametypes</term>
            <listitem><para>
                This option governs the automatic renaming of
                downloaded files.  Some servers do not present files
                with proper extensions to match their file type.  This
                can confuse various software and devices.  &hpodder;
                can automatically fix up extensions on such files.
                Each entry in the list in a MIME type, a colon, and
                the desired filename suffix.  Note that no whitespace
                is allowed around the colon.
              </para>
              <para>
                The default is: <literal>audio/mpeg:.mp3,
                audio/mp3:.mp3, x-audio/mp3:.mp3</literal>
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
      </refsect3>

    </refsect2>
  </refsect1>
              
  <refsect1 id="hpodder.curl.config">
    <indexterm><primary>Configuration File</><secondary>Curl</></>
    <title>Curl Configuration File</title>
    <para>
      Internally, &hpodder; uses the Curl application to perform
      downloads across the Internet.  Curl is a remarkably flexible
      application, and &hpodder; takes advantage of that to provide
      you with quite a few options.
    </para>
    <para>
      You can customize Curl as much as you like by creating a Curl
      configuration file in <filename>~/.hpodder/curlrc</filename>.
      Please see <application>curl</application>(1) for more details
      on the content of that file.
    </para>
    <para>Some things you can do with this file include restricting
    the maximum download rate, suppressing or adjusting the progress
    meter, configuring proxies, etc.
    </para>
  </refsect1>

  <refsect1 id="hpodder.tips">
    <title>Tips & Hints</title>
    <para>
      Here are a few tips and hints to make &hpodder; more pleasant
      for you.
    </para>
    <refsect2 id="hpodder.tips.proxy">
      <title>Going Through a Proxy</title>
      <indexterm><primary>Proxy</><secondary>Using with hpodder</></>
      <para>
        If your connections must go through a proxy, you have two
        options: set an environment varilable or configure the proxy
        in your <filename>~/.hpodder/curlrc</filename>.  If you use an
        environment variable, your settings will also impact other
        applications -- and that's probably what you want.  See the
        Environment section later for tips on doing that.
      </para>
    </refsect2>

    <refsect2 id="hpodder.tips.ratelimit">
      <title>Limiting Your Download Speed</title>
      <indexterm><primary>Download Rate</><secondary>Limiting</></>
      <para>
        Sometimes, you may not want &hpodder; to use all of your
        available bandwidth.  Perhaps you don't want it to slow down
        other activities too much.  To do this, just create a
        <filename>~/.hpodder/curlrc</filename> file.  Put in it
        something like this:
      </para>
      <programlisting>limit-rate=20k</programlisting>
      <para>
        This will limit the download rate to 20 KB/sec.
      </para>
      <para>
        This rate limitation is imperfect and may not do well during
        <command>update</command>, but it should do exactly what you
        want during <command>download</command>.
      </para>
    </refsect2>
  </refsect1>

  <refsect1 id="hpodder.environment">
    <title>Environment</title>
    <indexterm><primary>Environment Variables</></>
    <para>
      &hpodder; does not read any environment variables directly.
      However, it does pass on the environment to the
      programs it calls, such as Curl.  This can be useful for
      specifying proxies.  Please see
      <application>curl</application>(1) for more details.
      As specified in the Per-Podcast Command Options section, &hpodder;
      will also set certain variables for post-processing of
      downloaded files.
    </para>
  </refsect1>

  <refsect1 id="hpodder.conforming">
    <title>Conforming To</title>
    <itemizedlist>
      <listitem><para>The <ulink
      url="http://www.w3.org/XML/">Extensible Markup Language
            (XML)</ulink> standard (W3C)</para></listitem>
      <listitem><para><ulink
      url="http://blogs.law.harvard.edu/tech/rss">RSS 2.0</ulink>
      (Harvard Law)</para></listitem>
      <listitem><para>HTTP 1.1, FTP, plus SSL/TLS and any other
      protocols supported by Curl</para></listitem>
      <listitem><para>ID3 v1 and v2</para></listitem>
      </itemizedlist>
  </refsect1>

  <refsect1 id="hpodder.copyright">
    <title>Copyright</title>
    <indexterm><primary>Copyright</></>
    <para>
      &hpodder;, all code, documentation, files, and build scripts are
      Copyright &copy; 2006 John Goerzen.  All code, documentation,
      sripts, and files are under the following license unless
      otherwise noted:
    </para>
    <para>
      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.
    </para>
    
    <para>
      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.
    </para>
    
    <para>
      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    </para>
    <para>
      The GNU General Public License is available in the file COPYING
      in the source distribution.  Debian GNU/Linux users may find this in
      /usr/share/common-licenses/GPL-2.
    </para>
    <para>
      If the GPL is unacceptable for your uses, please e-mail me; alternative
      terms can be negotiated for your project.
    </para>
  </refsect1>
  
  <refsect1 id="hpodder.author">
    <title>Author</title>
    <para>
      &hpodder;, its modules, documentation, executables, and all
      included files, except where noted, was written by
      John Goerzen <email>jgoerzen@complete.org</email> and
      copyright is held as stated in the COPYRIGHT section.
    </para>
  </refsect1>

  <refsect1 id="dfs.seealso">
    <title>See Also</title>
    <para>
      <application>curl</application>(1),
      <application>mid3v2</application>(1)
    </para>
    <para>
      The &hpodder; homepage at <ulink
      url="http://software.complete.org/hpodder"></>,
      a general description of podcasting at
      <ulink url="http://en.wikipedia.org/wiki/Podcast"></>
    </para>
  </refsect1>
  
  </refentry>