+ small updates to plugin writer's guide

Original commit message from CVS:
+ small updates to plugin writer's guide
This commit is contained in:
Leif Johnson 2002-11-28 08:37:12 +00:00
parent e6d279fc4d
commit af236bd270
4 changed files with 167 additions and 136 deletions

View file

@ -5,10 +5,11 @@
<para> <para>
In this chapter you will learn how to construct the bare minimum code for a In this chapter you will learn how to construct the bare minimum code for a
new plugin. Starting from ground zero, you will see how to get the new plugin. Starting from ground zero, you will see how to get the
&GStreamer; template source. Then you will learn how to use a few simple &GStreamer; template source. Then you will learn how to use a few basic
command line tools to copy and modify a template plugin and thus create your tools to copy and modify a template plugin to create a new plugin. If you
new plugin. By the end of all this, you will have a functional audio filter follow the examples here, then by the end of this chapter you will have a
plugin that you can compile and test. functional audio filter plugin that you can compile and use in &GStreamer;
applications.
</para> </para>
<!-- ############ sect1 ############# --> <!-- ############ sect1 ############# -->
@ -20,16 +21,18 @@
can write the entire plugin by hand, or you can copy an existing plugin can write the entire plugin by hand, or you can copy an existing plugin
template and write the plugin code you need. The second method is by far template and write the plugin code you need. The second method is by far
the simpler of the two, so the first method will not even be described the simpler of the two, so the first method will not even be described
here. here. (Errm, that is, <quote>it is left as an exercise to the
reader.</quote>)
</para> </para>
<para> <para>
The first step is to check out a copy of the The first step is to check out a copy of the
<filename>gst-template</filename> CVS module to get an important tool and <filename>gst-template</filename> CVS module to get an important tool and
the source code template for the basic &GStreamer; plugin. To check out the source code template for a basic &GStreamer; plugin. To check out the
the <filename>gst-template</filename> module, type the following two <filename>gst-template</filename> module, make sure you are connected to
commands on a command line: the internet, and type the following commands at a command console:
</para> </para>
<screen> <screen>
<prompt>shell $ </prompt><userinput>cd .</userinput>
<prompt>shell $ </prompt><userinput>cvs -d:pserver:anonymous@cvs.gstreamer.sourceforge.net:/cvsroot/gstreamer login</userinput> <prompt>shell $ </prompt><userinput>cvs -d:pserver:anonymous@cvs.gstreamer.sourceforge.net:/cvsroot/gstreamer login</userinput>
Logging in to :pserver:anonymous@cvs.gstreamer.sourceforge.net:2401/cvsroot/gstreamer Logging in to :pserver:anonymous@cvs.gstreamer.sourceforge.net:2401/cvsroot/gstreamer
CVS password: CVS password:
@ -47,7 +50,7 @@ U gst-template/gst-app/src/Makefile.am
</screen> </screen>
<para> <para>
After the first command, you will have to press <keycap>ENTER</keycap> to After the first command, you will have to press <keycap>ENTER</keycap> to
log in to the CVS server. You might have to log in twice. The second log in to the CVS server. (You might have to log in twice.) The second
command will check out a series of files and directories into <filename command will check out a series of files and directories into <filename
class="directory">./gst-template</filename>. The template you will be class="directory">./gst-template</filename>. The template you will be
using is in <filename using is in <filename
@ -59,8 +62,8 @@ U gst-template/gst-app/src/Makefile.am
<!-- ############ sect1 ############# --> <!-- ############ sect1 ############# -->
<sect1 id="sect1-boiler-filterstamp" xreflabel="Using Filterstamp"> <sect1 id="sect1-boiler-project-stamp" xreflabel="Using the Project Stamp">
<title>Using Filterstamp</title> <title>Using the Project Stamp</title>
<para> <para>
The first thing to do when making a new element is to specify some basic The first thing to do when making a new element is to specify some basic
details about it: what its name is, who wrote it, what version number it details about it: what its name is, who wrote it, what version number it
@ -72,10 +75,12 @@ U gst-template/gst-app/src/Makefile.am
The standard way of defining the boilerplate is simply to write some code, The standard way of defining the boilerplate is simply to write some code,
and fill in some structures. As mentioned in the previous section, the and fill in some structures. As mentioned in the previous section, the
easiest way to do this is to copy a template and add functionality easiest way to do this is to copy a template and add functionality
according to your needs. To help you do so, there is a script called according to your needs. To help you do so, there are some tools in the
<command>pluginstamp.sh</command> in the <filename <filename class="directory">./gst-template/tools/</filename> directory.
class="directory">tools/</filename> directory of the One tool, <filename>gst-quick-stamp</filename>, is a quick command line
<filename>gst-template</filename> source tree that does exactly this. tool. The other, <filename>gst-project-stamp</filename>, is a full GNOME
druid application that takes you through the steps of creating a new
project (either a plugin or an application).
</para> </para>
<para> <para>
To use <command>pluginstamp.sh</command>, first open up a terminal window. To use <command>pluginstamp.sh</command>, first open up a terminal window.
@ -97,9 +102,9 @@ U gst-template/gst-app/src/Makefile.am
<para> <para>
Note that capitalization is important for the name of the plugin. Under Note that capitalization is important for the name of the plugin. Under
some operating systems, capitalization is also important when specifying some operating systems, capitalization is also important when specifying
directory names. For example, the directory names. For example, the following commands create the
following commands create the ExampleFilter plugin based on the plugin ExampleFilter plugin based on the plugin template and put the output files
template and put the output files in a new directory called <filename in a new directory called <filename
class="directory">~/src/examplefilter/</filename>: class="directory">~/src/examplefilter/</filename>:
</para> </para>
<screen> <screen>

View file

@ -32,7 +32,7 @@
<!ENTITY APPENDIX_PYTHON SYSTEM "appendix_python.xml"> <!ENTITY APPENDIX_PYTHON SYSTEM "appendix_python.xml">
<!ENTITY GStreamer "<application>GStreamer</application>"> <!ENTITY GStreamer "<application>GStreamer</application>">
<!ENTITY GstVersion "0.4.1"> <!ENTITY GstVersion "0.4.2.2">
<!ENTITY GstAppDevMan "<emphasis>GStreamer Application Development Manual</emphasis>"> <!ENTITY GstAppDevMan "<emphasis>GStreamer Application Development Manual</emphasis>">
<!ENTITY GstLibRef "<emphasis>GStreamer Library Reference</emphasis>"> <!ENTITY GstLibRef "<emphasis>GStreamer Library Reference</emphasis>">
]> ]>
@ -56,13 +56,12 @@
</para> </para>
<para> <para>
This guide is intended to help you understand the &GStreamer; framework This guide is intended to help you understand the &GStreamer; framework
so you can develop new plugins to extend &GStreamer;'s functionality. (version &GstVersion;) so you can develop new plugins to extend the
This guide introduces most of the basic plugin writing issues in version existing functionality. The guide addresses most issues by following the
&GstVersion; of &GStreamer;. This guide presents most issues in the development of an example plugin &mdash; an audio filter plugin &mdash;
context of an example audio filter plugin written in C. However, the written in C. However, the later parts of the guide also present some
guide also addresses some issues involved in writing other types of issues involved in writing other types of plugins, and the end of the
plugins, and the end of the guide also describes some of the Python guide describes some of the Python bindings for &GStreamer;.
bindings for &GStreamer;.
</para> </para>
</partintro> </partintro>
@ -76,22 +75,22 @@
<title>Building a Filter</title> <title>Building a Filter</title>
<partintro> <partintro>
<para> <para>
You now have the neccessary concepts to build your first plugin. In this You are now ready to learn how to build a plugin. In this part of the
part of the guide, you will learn how to apply these concepts to write a guide, you will learn how to apply basic &GStreamer; and GNOME
simple audio filter plugin. The previous parts of the guide have programming concepts to write a simple plugin. The previous parts of the
contained no explicit example code, perhaps making things a bit abstract guide have contained no explicit example code, perhaps making things a
and difficult to understand. In contrast, this section will present both bit abstract and difficult to understand. In contrast, this section will
applications and code by following the development of an example audio present both applications and code by following the development of an
filter plugin called <quote>ExampleFilter</quote>. example audio filter plugin called <quote>ExampleFilter</quote>.
</para> </para>
<para> <para>
The example filter will begin with a single input pad and a single The example filter will begin with a single input pad and a single
output pad. The filter will, at first, simply pass data through without output pad. The filter will, at first, simply pass media and event data
modification. But by the end of this part of the guide, you will learn from its sink pad to its source pad without modification. But by the end
to add some more interesting functionality, including properties and of this part of the guide, you will learn to add some more interesting
signal handlers. And after reading the next part of the guide, <xref functionality, including properties and signal handlers. And after
linkend="part-advanced"/>, you will be able to add even more reading the next part of the guide, <xref linkend="part-advanced"/>, you
functionality to your plugins. will be able to add even more functionality to your plugins.
</para> </para>
<para> <para>
The example code used in this part of the guide can be found in The example code used in this part of the guide can be found in

View file

@ -4,9 +4,9 @@
<title>Basic Concepts</title> <title>Basic Concepts</title>
<para> <para>
This chapter of the guide introduces the basic concepts of &GStreamer;. This chapter of the guide introduces the basic concepts of &GStreamer;.
Understanding these concepts will help you see the issues involved in Understanding these concepts will help you grok the issues involved in
extending &GStreamer;. Many of these concepts are explained in greater extending &GStreamer;. Many of these concepts are explained in greater
detail in the &GstAppDevMan;. The basic concepts presented here serve mainly detail in the &GstAppDevMan;; the basic concepts presented here serve mainly
to refresh your memory. to refresh your memory.
</para> </para>
@ -17,29 +17,30 @@
<para> <para>
Elements are at the core of &GStreamer;. In the context of plugin Elements are at the core of &GStreamer;. In the context of plugin
development, an <emphasis>element</emphasis> is an object derived from the development, an <emphasis>element</emphasis> is an object derived from the
<classname>GstElement</classname> class. An element provides some sort of <classname>GstElement</classname> class. Elements provide some sort of
functionality when connected with other elements. Without elements, functionality when connected with other elements: For example, a source
&GStreamer; is just a bunch of conceptual pipe fittings with nothing to element provides data to a stream, and a filter element acts on the data
connect. A large number of elements ship with &GStreamer;, but extra in a stream. Without elements, &GStreamer; is just a bunch of conceptual
elements can also be written. The purpose of this guide is to help you pipe fittings with nothing to connect. A large number of elements ship
learn to create new elements, which are encapsulated in plugins as with &GStreamer;, but extra elements can also be written.
described below.
</para>
<para>
A <emphasis>filter</emphasis> is an important type of element that
processes a stream of data, as opposed to producing or consuming streams
of data. Producers and consumers of data are called
<emphasis>source</emphasis> and <emphasis>sink</emphasis> elements,
respectively.
</para> </para>
<para> <para>
Just writing a new element is not entirely enough, however: You will need Just writing a new element is not entirely enough, however: You will need
to encapsulate your element in a plugin to enable &GStreamer; to use it. A to encapsulate your element in a <emphasis>plugin</emphasis> to enable
<emphasis>plugin</emphasis> is essentially a loadable block of code, &GStreamer; to use it. A plugin is essentially a loadable block of code,
usually a shared object file or dynamically linked library. A single usually called a shared object file or a dynamically linked library. A
plugin may contain the implementation of several elements, or just a single plugin may contain the implementation of several elements, or just
single one. For simplicity, this guide concentrates primarily on plugins a single one. For simplicity, this guide concentrates primarily on plugins
containing one filter type element. containing one element.
</para>
<para>
A <emphasis>filter</emphasis> is an important type of element that
processes a stream of data. Producers and consumers of data are called
<emphasis>source</emphasis> and <emphasis>sink</emphasis> elements,
respectively. Elements that connect other elements together are called
<emphasis>autoplugger</emphasis> elements, and a <emphasis>bin</emphasis>
element contains other elements. Bins are often responsible for scheduling
the elements that they contain so that data flows smoothly.
</para> </para>
<para> <para>
The plugin mechanism is used everywhere in &GStreamer;, even if only the The plugin mechanism is used everywhere in &GStreamer;, even if only the
@ -66,19 +67,29 @@
<para> <para>
<emphasis>Pads</emphasis> are used to negotiate connections and data flow <emphasis>Pads</emphasis> are used to negotiate connections and data flow
between elements in &GStreamer;. A pad can be viewed as a between elements in &GStreamer;. A pad can be viewed as a
<quote>place</quote> on an element where connections may be made with <quote>place</quote> or <quote>port</quote> on an element where
other elements. Pads have specific data handling capabilities: That is, a connections may be made with other elements. Pads have specific data
pad only knows how to give or receive certain types of data. Connections handling capabilities: A pad only knows how to give or receive certain
are only allowed when the capabilities of two pads are compatible. types of data. Connections are only allowed when the capabilities of two
pads are compatible.
</para> </para>
<para> <para>
An analogy may be helpful here. A pad is similar to a plug or jack on a An analogy may be helpful here. A pad is similar to a plug or jack on a
physical device. Consider, for example, a home theater system consisting physical device. Consider, for example, a home theater system consisting
of an amplifier, a DVD player, and a television. Connecting the DVD player of an amplifier, a DVD player, and a (silent) video projector. Connecting
to the amplifier is allowed only because both devices have audio jacks, the DVD player to the amplifier is allowed because both devices have audio
and connecting the television to the DVD player is allowed because both jacks, and connecting the projector to the DVD player is allowed because
devices have compatible video jacks. Pads in &GStreamer; serve the same both devices have compatible video jacks. Connections between the
purpose as the jacks in the home theater system. projector and the amplifier may not be made because the projector and
amplifier have different types of jacks. Pads in &GStreamer; serve the
same purpose as the jacks in the home theater system.
</para>
<para>
For the moment, all data in &GStreamer; flows one way through a connection
between elements. Data flows out of one element through one or more
<emphasis>source pads</emphasis>, and elements accept incoming data through
one or more <emphasis>sink pads</emphasis>. Source and sink elements have
only source and sink pads, respectively.
</para> </para>
<para> <para>
See the &GstLibRef; for the current implementation details of a <ulink See the &GstLibRef; for the current implementation details of a <ulink
@ -95,8 +106,8 @@
All streams of data in &GStreamer; are chopped up into chunks that are All streams of data in &GStreamer; are chopped up into chunks that are
passed from a source pad on one element to a sink pad on another element. passed from a source pad on one element to a sink pad on another element.
<emphasis>Buffers</emphasis> are structures used to hold these chunks of <emphasis>Buffers</emphasis> are structures used to hold these chunks of
data. Buffers can be of any size, theoretically. Buffers may contain any data. Buffers can be of any size, theoretically, and they may contain any
sort of data that the two pads involved know how to handle: Normally, a sort of data that the two connected pads know how to handle. Normally, a
buffer contains a chunk of some sort of audio or video data that flows buffer contains a chunk of some sort of audio or video data that flows
from one element to another. from one element to another.
</para> </para>
@ -125,8 +136,7 @@
A reference count indicating the number of elements currently A reference count indicating the number of elements currently
holding a reference to the buffer. When the buffer reference count holding a reference to the buffer. When the buffer reference count
falls to zero, the buffer will be unlinked, and its memory will be falls to zero, the buffer will be unlinked, and its memory will be
freed in some sense (see the next part about <xref freed in some sense (see below for more details).
linkend="sect2-buffers-bufferpools"/> for more details).
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -143,15 +153,29 @@
<para> <para>
Buffers can be allocated using various schemes, and they may either be Buffers can be allocated using various schemes, and they may either be
passed on by an element or unreferenced, thus freeing the memory used by passed on by an element or unreferenced, thus freeing the memory used by
the buffer. the buffer. Buffer allocation and unlinking are important concepts when
dealing with real time media processing, since memory allocation is
relatively slow on most systems.
</para> </para>
<para> <para>
Normally, filter elements in &GStreamer; deal with a buffer in place, To improve the latency in a media pipeline, many &GStreamer; elements
meaning that they do not create or destroy buffers. Sometimes, however, use a <emphasis>buffer pool</emphasis> to handle buffer allocation and
elements might need to alter the reference count of a buffer to copy or unlinking. A buffer pool is a relatively large chunk of memory that is
destroy the buffer, or to create a new buffer. For the most part, this the &GStreamer; process requests early on from the operating system.
guide does not deal with elements that alter a buffer's reference count, Later, when elements request memory for a new buffer, the buffer pool
but buffer referencing is an important concept to know. can serve the request quickly by giving out a piece of the allocated
memory. This saves a call to the operating system and lowers latency.
[If it seems at this point like &GStreamer; is acting like an operating
system (doing memory management, etc.), don't worry: &GStreamer;OS isn't
due out for quite a few years!]
</para>
<para>
Normally in a media pipeline, most filter elements in &GStreamer; deal
with a buffer in place, meaning that they do not create or destroy
buffers. Sometimes, however, elements might need to alter the reference
count of a buffer, either by copying or destroying the buffer, or by
creating a new buffer. These topics are generally reserved for
non-filter elements, so they will be addressed at that point.
</para> </para>
</sect2> </sect2>
</sect1> </sect1>
@ -456,12 +480,14 @@
<sect1 id="sect1-basics-events" xreflabel="Events"> <sect1 id="sect1-basics-events" xreflabel="Events">
<title>Events</title> <title>Events</title>
<para> <para>
Events are a special type of data in &GStreamer;. Sometimes elements in a media processing pipeline need to know that
<emphasis>Events</emphasis> indicate some sort of notable event that has something has happened. An <emphasis>event</emphasis> is a special type of
happened somewhere in an element's pipeline. Just like any other data data in &GStreamer; designed to serve this purpose. Events describe some
type, an event comes to an element through its pads. Events are contained sort of activity that has happened somewhere in an element's pipeline, for
in a <classname>GstBuffer</classname>, so an event buffer will contain example, the end of the media stream or a clock discontinuity. Just like
only an event, not any other type of data. any other data type, an event comes to an element on a sink pad and is
contained in a normal buffer. Unlike normal stream buffers, though, an
event buffer contains only an event, not any media stream data.
</para> </para>
<para> <para>
See the &GstLibRef; for the current implementation details of a <ulink See the &GstLibRef; for the current implementation details of a <ulink

View file

@ -87,76 +87,89 @@
<listitem> <listitem>
<para> <para>
<guilabel><xref linkend="part-building"/></guilabel> &mdash; <guilabel><xref linkend="part-building"/></guilabel> &mdash;
Introduction to the structure of a plugin. This part covers all the Introduction to the structure of a plugin, using an example audio
different steps you have to perform to build a basic audio filter filter for illustration.
plugin. The discussion begins by giving examples of generating the </para>
basic structures with <xref linkend="cha-building-boiler"/>. Then you <para>
will learn how to write the code to get a basic filter plugin working. This part covers all the basic steps you generally need to perform to
Several chapters cover these concepts, including <xref build a plugin. The discussion begins by giving examples of generating
the basic structures with <xref linkend="cha-building-boiler"/>. Then
you will learn how to write the code to get a basic filter plugin
working: These steps include chapters on <xref
linkend="cha-building-types"/>, <xref linkend="cha-building-pads"/>, linkend="cha-building-types"/>, <xref linkend="cha-building-pads"/>,
<xref linkend="cha-building-chainfn"/>, and <xref <xref linkend="cha-building-chainfn"/>, and <xref
linkend="cha-building-state"/>. linkend="cha-building-state"/>.
</para> </para>
<para> <para>
After you have finished these chapters, you will have a working After you have finished the first steps, you will be able to create a
plugin, but your new plugin might not have all the functionality you working plugin, but your new plugin might not have all the
need. To provide some standard functionality, you will learn how to functionality you need. To provide some standard functionality, you
add features to a filter in the chapters on <xref will learn how to add more features to a new plugin. These features
linkend="cha-building-props"/> and <xref are described in the chapters on <xref linkend="cha-building-props"/>
linkend="cha-building-signals"/>. Finally, you will learn to test your and <xref linkend="cha-building-signals"/>. Finally, you will see in
new plugin in <xref linkend="cha-building-testapp"/>. <xref linkend="cha-building-testapp"/> how to write a short test
application to try out your new plugin.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<guilabel><xref linkend="part-advanced"/></guilabel> &mdash; <guilabel><xref linkend="part-advanced"/></guilabel> &mdash;
Information on advanced features of &GStreamer; plugin development. Information on advanced features of &GStreamer; plugin development.
</para>
<para>
After learning about the basic steps, you should be able to create a After learning about the basic steps, you should be able to create a
functional audio or video filter plugin with some nice features. functional audio or video filter plugin with some nice features.
However, &GStreamer; offers more for plugin writers. This part of the However, &GStreamer; offers more for plugin writers. This part of the
guide includes chapters on <xref linkend="cha-advanced-scheduling"/>, guide includes chapters on more advanced topics, such as <xref
<xref linkend="cha-advanced-request"/>, <xref linkend="cha-advanced-scheduling"/>, <xref
linkend="cha-advanced-request"/>, <xref
linkend="cha-advanced-clock"/>, <xref linkend="cha-advanced-clock"/>, <xref
linkend="cha-advanced-dparams"/>, and <xref linkend="cha-advanced-dparams"/>, and <xref
linkend="cha-advanced-midi"/>. Since these features are more advanced, linkend="cha-advanced-midi"/>. Since these features are more advanced,
the chapters can basically be read in any order, as you need the the chapters can basically be read in any order, as you find that your
features for your custom plugins. plugins require these features.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<guilabel><xref linkend="part-other"/></guilabel> &mdash; Explanation <guilabel><xref linkend="part-other"/></guilabel> &mdash; Explanation
of writing source and sink plugins. Although the concepts introduced of writing other plugin types.
in the two previous parts of this guide apply to filter plugins, many </para>
of the concepts apply equally to source and sink plugins. This part <para>
will take a look at creating source and sink type plugins for Because the first two parts of the guide use an audio filter as an
&GStreamer; in the chapters on <xref linkend="cha-other-source"/> and example, the concepts introduced apply to filter plugins. But many of
<xref linkend="cha-other-sink"/>. The chapter on <xref the concepts apply equally to other plugin types, including sources,
linkend="cha-other-autoplugger"/> describes writing autoplugger sinks, and autopluggers. This part of the guide presents the issues
plugins. that arise when working on these more specialized plugin types. The
part includes chapters on <xref linkend="cha-other-source"/>, <xref
linkend="cha-other-sink"/>, <xref linkend="cha-other-scheduler"/>, and
<xref linkend="cha-other-autoplugger"/>.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<guilabel><xref linkend="part-appendix"/></guilabel> &mdash; The <guilabel><xref linkend="part-appendix"/></guilabel> &mdash; Further
appendices contain some information that stubbornly refused to fit information for plugin developers.
cleanly in other sections of this guide, like the <xref </para>
linkend="cha-appendix-checklist"/> and <xref <para>
The appendices contain some information that stubbornly refuses to fit
cleanly in other sections of the guide. This information includes
<xref linkend="cha-appendix-checklist"/> and <xref
linkend="cha-appendix-python"/>. FIXME: organize better. linkend="cha-appendix-python"/>. FIXME: organize better.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>
The remainder of this introductory part presents a short overview of the The remainder of this introductory part of the guide presents a short
basic concepts involved in &GStreamer; plugin development. People familiar overview of the basic concepts involved in &GStreamer; plugin development.
with the &GstAppDevMan; can use this short overview to refresh their Topics covered include <xref linkend="sect1-basics-elements"/>, <xref
memory. Topics covered include <xref linkend="sect1-basics-elements"/>, linkend="sect1-basics-pads"/>, <xref linkend="sect1-basics-buffers"/>,
<xref linkend="sect1-basics-pads"/>, <xref <xref linkend="sect1-basics-types"/>, and <xref
linkend="sect1-basics-buffers"/>, <xref linkend="sect1-basics-types"/>, linkend="sect1-basics-events"/>. If you are already familiar with this
and <xref linkend="sect1-basics-events"/>. information, you can use this short overview to refresh your memory, or
you can skip to <xref linkend="part-building"/>.
</para> </para>
<para> <para>
As you can see, there a lot to learn, so let's get started! As you can see, there a lot to learn, so let's get started!
</para> </para>
@ -175,18 +188,6 @@
This will allow your plugin to operate on a completely new media type. This will allow your plugin to operate on a completely new media type.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
Creating custom schedulers when the default schedulers are
insufficient.
</para>
</listitem>
<listitem>
<para>
Creating custom autopluggers when the default ones are insufficient
for your needs.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</sect1> </sect1>
</chapter> </chapter>