conversion to docbook-xml. i don't have to ask that this be testing, because not ionly is it perfect, but i'm sure yo...

Original commit message from CVS:
conversion to docbook-xml. i don't have to ask that this be testing, because
not ionly is it perfect, but i'm sure you folks will learn that on your own :-)
This commit is contained in:
Andy Wingo 2001-12-15 23:13:04 +00:00
parent fb32f9a4ac
commit d2c3b2087d
69 changed files with 3142 additions and 230 deletions

View file

@ -1,21 +1,25 @@
manualname = gst-plugin-writers-guide
htmlname = index.html
DOC=gst-plugin-writers-guide
MAIN=$(DOC).xml
XML=$(shell echo *.xml)
XSLFO=$(srcdir)/../xsl/fo.xsl
XSLFOMODS=$(srcdir)/../xsl/ulink.xsl $(srcdir)/../xsl/keycombo.xsl
XSLHTML=$(srcdir)/../xsl/html.xsl
XSLHTMLMODS=$(srcdir)/../xsl/fileext.xsl $(srcdir)/../xsl/admon.xsl \
$(srcdir)/../xsl/keycombo.xsl $(srcdir)/../xsl/css.xsl
XSLS=$(XSLFO) $(XSLFOMODS) $(XSLHTML) $(XSLHTMLMODS)
FIGS= # $(shell echo *.fig) (uncomment when pngs are added)
PNGS=$(FIGS:.fig=.png)
PDFS=$(FIGS:.fig=.pdf)
SRC=$(XML)
CSS=base.css
sgml_files = gst-plugin-writers-guide.sgml \
titlepage.sgml \
intro.sgml \
testapp.sgml \
loopbased.sgml \
buffers.sgml \
srcnsink.sgml \
statemanage.sgml \
checklist.sgml
STYLESHEET_IMAGES=/usr/share/doc/docbook-xsl/images
fig_files =
eps_files =
png_files =
EXTRA_DIST = $(XML) $(FIGS)
EXTRA_DIST = $(sgml_files) $(fig_files)
## FIXME if we don't do this they don't get cleaned up in make distcheck
## but maybe this is not the best way to do it
CONFIG_CLEAN_FILES = $(XML) $(FIGS)
include $(srcdir)/../manuals.mak

0
docs/fwg/base.css Normal file
View file

View file

@ -1,20 +1,17 @@
<!DOCTYPE book PUBLIC "-//GNOME//DTD DocBook PNG Variant V1.0//EN" "" [
<?xml version='1.0'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % magic-entities SYSTEM "magic">
%magic-entities;
<!ENTITY TITLEPAGE SYSTEM "titlepage.sgml">
<!ENTITY INTRO SYSTEM "intro.sgml">
<!ENTITY TESTAPP SYSTEM "testapp.sgml">
<!ENTITY LOOPBASED SYSTEM "loopbased.sgml">
<!ENTITY BUFFERS SYSTEM "buffers.sgml">
<!ENTITY SRCNSINK SYSTEM "srcnsink.sgml">
<!ENTITY STATEMANAGE SYSTEM "statemanage.sgml">
<!ENTITY CHECKLIST SYSTEM "checklist.sgml">
<!ENTITY GStreamer "<application>GStreamer</application>">
]>

1
docs/fwg/magic-pdf Normal file
View file

@ -0,0 +1 @@
<!ENTITY magic "pdf">

1
docs/fwg/magic-png Normal file
View file

@ -0,0 +1 @@
<!ENTITY magic "png">

View file

@ -1,80 +1,24 @@
manualname = gstreamer-manual
htmlname = index.html
DOC=gstreamer-manual
MAIN=$(DOC).xml
XML=$(shell echo *.xml)
XSLFO=$(srcdir)/../xsl/fo.xsl
XSLFOMODS=$(srcdir)/../xsl/ulink.xsl $(srcdir)/../xsl/keycombo.xsl
XSLHTML=$(srcdir)/../xsl/html.xsl
XSLHTMLMODS=$(srcdir)/../xsl/fileext.xsl $(srcdir)/../xsl/admon.xsl \
$(srcdir)/../xsl/keycombo.xsl $(srcdir)/../xsl/css.xsl
XSLS=$(XSLFO) $(XSLFOMODS) $(XSLHTML) $(XSLHTMLMODS)
FIGS=$(shell echo *.fig)
PNGS=$(FIGS:.fig=.png)
PDFS=$(FIGS:.fig=.pdf)
SRC=$(XML)
CSS=base.css
sgml_files = gstreamer-manual.sgml \
advanced.sgml \
autoplugging.sgml \
bins.sgml \
buffers.sgml \
components.sgml \
quotes.sgml \
pads.sgml \
connections.sgml \
cothreads.sgml \
dynamic.sgml \
elements.sgml \
factories.sgml \
goals.sgml \
helloworld.sgml \
helloworld2.sgml \
init.sgml \
intro.sgml \
motivation.sgml \
plugins.sgml \
programs.sgml \
debugging.sgml \
queues.sgml \
states.sgml \
threads.sgml \
typedetection.sgml \
utility.sgml \
xml.sgml
STYLESHEET_IMAGES=/usr/share/doc/docbook-xsl/images
fig_files = bin-element.fig \
bin-element-ghost.fig \
connected-elements.fig \
filter-element-multi.fig \
filter-element.fig \
hello-world.fig \
mime-world.fig \
queue.fig \
sink-element.fig \
src-element.fig \
state-diagram.fig \
thread.fig
eps_files = images/bin-element.eps \
images/bin-element-ghost.eps \
images/connected-elements.eps \
images/filter-element-multi.eps \
images/filter-element.eps \
images/hello-world.eps \
images/mime-world.eps \
images/queue.eps \
images/sink-element.eps \
images/src-element.eps \
images/state-diagram.eps \
images/thread.eps
png_files = images/bin-element.png \
images/bin-element-ghost.png \
images/connected-elements.png \
images/filter-element-multi.png \
images/filter-element.png \
images/hello-world.png \
images/mime-world.png \
images/queue.png \
images/sink-element.png \
images/src-element.png \
images/state-diagram.png \
images/thread.png
EXTRA_DIST = $(sgml_files) $(fig_files)
EXTRA_DIST = $(XML) $(FIGS)
## FIXME if we don't do this they don't get cleaned up in make distcheck
## but maybe this is not the best way to do it
CONFIG_CLEAN_FILES = $(sgml_files) $(fig_files)
CONFIG_CLEAN_FILES = $(XML) $(FIGS)
include $(srcdir)/../manuals.mak

View file

@ -90,7 +90,7 @@
<title>The Hello world pipeline with MIME types</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/mime-world" format="PNG">
<imagedata fileref="images/mime-world.&magic;" format="&magic;" />
</imageobject>
</mediaobject>

View file

@ -48,7 +48,7 @@
<title>a thread</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/thread" format="PNG">
<imagedata fileref="images/thread.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>

View file

@ -0,0 +1,98 @@
<chapter id="cha-debugging">
<title>Debugging</title>
<para>
GStreamer has an extensive set of debugging tools for
plugin developers.
</para>
<sect1>
<title>Command line options</title>
<para>
Applications using the GStreamer libraries accept the following set
of command line argruments to enable the debugging system.
</para>
<para>
<itemizedlist>
<listitem>
<para>
<option>--gst-debug-mask=<replaceable>mask</replaceable></option>
Sets the mask for the debugging output.
</para>
</listitem>
<listitem>
<para>
<option>--gst-info-mask=<replaceable>mask</replaceable></option>
Sets the mask for the info output.
</para>
</listitem>
<listitem>
<para>
<option>--gst-mask=<replaceable>mask</replaceable></option>
Sets the mask for the info *and* the debug output.
</para>
</listitem>
<listitem>
<para>
<option>--gst-plugin-spew</option>
Enable printout of errors while loading GST plugins.
</para>
</listitem>
<listitem>
<para>
<option>--gst-plugin-path=<replaceable>PATH</replaceable></option>
Add a directory to the plugin search path.
</para>
</listitem>
<listitem>
<para>
<option>--help</option> Print the a short desciption of the
options and an overview of the current debugging/info masks
set.
</para>
</listitem>
</itemizedlist>
</para>
<para>
The follwing table gives an overview of the mask values and
their meaning. (enabled) means that the corresponding flag
has been set.
</para>
<programlisting>
Mask (to be OR'ed) info/debug FLAGS
--------------------------------------------------------
0x00000001 (enabled)/ GST_INIT
0x00000002 / COTHREADS
0x00000004 / COTHREAD_SWITCH
0x00000008 / AUTOPLUG
0x00000010 / AUTOPLUG_ATTEMPT
0x00000020 / PARENTAGE
0x00000040 / STATES
0x00000080 / PLANING
0x00000100 / SCHEDULING
0x00000200 / OPERATION
0x00000400 / BUFFER
0x00000800 / CAPS
0x00001000 / CLOCK
0x00002000 / ELEMENT_PADS
0x00004000 / ELEMENTFACTORY
0x00008000 / PADS
0x00010000 / PIPELINE
0x00020000 / PLUGIN_LOADING
0x00040000 / PLUGIN_ERRORS
0x00080000 / PLUGIN_INFO
0x00100000 / PROPERTIES
0x00200000 / THREAD
0x00400000 / TYPES
0x00800000 / XML
0x01000000 / NEGOTIATION
0x02000000 / REFCOUNTING
</programlisting>
</sect1>
<sect1>
<title>Adding a custom debug handler</title>
<para>
</para>
</sect1>
</chapter>

0
docs/manual/base.css Normal file
View file

View file

@ -20,7 +20,7 @@
<title>Visualisation of a <classname>GstBin</classname> element with some elements in it</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/bin-element" format="PNG">
<imagedata fileref="images/bin-element.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
@ -176,7 +176,7 @@
<title>Visualisation of a <classname>GstBin</classname> element with a ghostpad</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/bin-element-ghost" format="PNG">
<imagedata fileref="images/bin-element-ghost.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>

View file

@ -36,7 +36,7 @@
<title>Visualisation of a source element</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/src-element" format="PNG">
<imagedata fileref="images/src-element.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
@ -65,7 +65,7 @@
<title>Visualisation of a filter element</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/filter-element" format="PNG">
<imagedata fileref="images/filter-element.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
@ -79,7 +79,7 @@
more than one output pad</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/filter-element-multi" format="PNG">
<imagedata fileref="images/filter-element-multi.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
@ -103,7 +103,7 @@
<title>Visualisation of a sink element</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/sink-element" format="PNG">
<imagedata fileref="images/sink-element.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>

View file

@ -203,7 +203,7 @@ main (int argc, char *argv[])
<title>The Hello world pipeline</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/hello-world" format="PNG">
<imagedata fileref="images/hello-world.&magic;" format="&magic;" />
</imageobject>
</mediaobject>

218
docs/manual/bins.xml Normal file
View file

@ -0,0 +1,218 @@
<chapter id="cha-bins">
<title>Bins</title>
<para>
A Bin is a container element. You can add elements to a bin. Since a bin is
an <classname>GstElement</classname> itself, it can also be added to another bin.
</para>
<para>
Bins allow you to combine connected elements into one logical element. You do
not deal with the individual elements anymore but with just one element, the bin.
We will see that this is extremely powerfull when you are going to construct
complex pipelines since it allows you to break up the pipeline in smaller chunks.
</para>
<para>
The bin will also manage the elements contained in it. It will figure out how
the data will flow in the bin and generate an optimal plan for that data flow. Plan
generation is one of the most complicated procedures in GStreamer.
</para>
<figure float="1" id="sec-bin-img">
<title>Visualisation of a <classname>GstBin</classname> element with some elements in it</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/bin-element.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
<para>
There are two standard bins available to the GStreamer programmer:
<itemizedlist>
<listitem>
<para>
A pipeline (<classname>GstPipeline</classname>). Which is a generic container you will
use most of the time. The toplevel bin has to be a pipeline.
</para>
</listitem>
<listitem>
<para>
A thread (<classname>GstThread</classname>). All the elements in the thread bin will
run in a separate thread. You will have to use this bin if you carfully have to
synchronize audio and video for example. You will learn more about threads in.. <!-- FIXME -->
</para>
</listitem>
</itemizedlist>
</para>
<sect1 id="sec-bin-create">
<title>Creating a bin</title>
<para>
You create a bin with a specified name 'mybin' with:
</para>
<programlisting>
GstElement *bin;
gst_bin_new ("mybin");
...
</programlisting>
<para>
A thread can be created with:
</para>
<programlisting>
GstElement *thread;
gst_thread_new ("mythread");
...
</programlisting>
<para>
Pipelines are created with gst_pipeline_new ("name");
</para>
</sect1>
<sect1 id="sec-bin-adding">
<title>Adding elements to a bin</title>
<para>
Elements are added to a bin with the following code sample:
</para>
<programlisting>
GstElement *element;
GstElement *bin;
bin = gst_bin_new ("mybin");
element = gst_elementfactory_make ("mpg123", "decoder");
gst_bin_add (GST_BIN (bin), element);
...
</programlisting>
<para>
Bins and threads can be added to other bins too. This allows you to create nested
bins.
</para>
<para>
To get an element from the bin you can use:
</para>
<programlisting>
GstElement *element;
element = gst_bin_get_by_name (GST_BIN (bin), "decoder");
...
</programlisting>
<para>
You can see that the name of the element becomes very handy for retrieving the
element from an bin by using the elements name. gst_bin_get_by_name () will
recursively search nested bins.
</para>
<para>
To get a list of elements in a bin, use:
</para>
<programlisting>
GList *elements;
elements = gst_bin_get_list (GST_BIN (bin));
while (elements) {
GstElement *element = GST_ELEMENT (elements-&gt;data);
g_print ("element in bin: &percnt;s\n", gst_element_get_name (element));
elements = g_list_next (elements);
}
...
</programlisting>
<para>
To remove an element from a bin use:
</para>
<programlisting>
GstElement *element;
gst_bin_remove (GST_BIN (bin), element);
...
</programlisting>
</sect1>
<sect1 id="sec-bin-custom">
<title>Custom bins</title>
<para>
The application programmer can create custom bins packed with elements to perform a
specific task. This allow you to write an MPEG audio decoder with just the follwing lines
of code:
<programlisting>
// create the mp3player element
GstElement *mp3player = gst_elementfactory_make ("mp3player", "mp3player");
// set the source mp3 audio file
g_object_set (G_OBJECT (mp3player), "location", "helloworld.mp3", NULL);
// start playback
gst_element_set_state (GST_ELEMENT (mp3player), GST_STATE_PLAYING);
...
// pause playback
gst_element_set_state (GST_ELEMENT (mp3player), GST_STATE_PAUSED);
...
// stop
gst_element_set_state (GST_ELEMENT (mp3player), GST_STATE_NULL);
</programlisting>
Custom bins can be created with a plugin or an XML description. You will find more
information about creating custom bin in the Filter-Writers-Guide.
</para>
</sect1>
<sect1 id="sec-bin-ghostpads">
<title>Ghostpads</title>
<para>
You can see from figure ... how a bin has no pads of its own. This is where Ghostpads
come into play.
</para>
<para>
A ghostpad is a pad from some element in the bin that has been promoted to the bin.
This way, the bin also has a pad. The bin becomes just another element with a pad and
you can then use the bin just like any other element. This is a very important feature
for creating custom bins.
</para>
<figure float="1" id="sec-bin-ghost-img">
<title>Visualisation of a <classname>GstBin</classname> element with a ghostpad</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/bin-element-ghost.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
<para>
Above is a representation of a ghostpad. the sinkpad of element one is now also a pad
of the bin.
</para>
<para>
Ghostpads can actually be added to all <classname>GstElement</classname>s and not just
<classname>GstBin</classname>s. Use the following code example to add a ghostpad to a bin:
</para>
<programlisting>
GstElement *bin;
GstElement *element;
element = gst_elementfactory_create ("mpg123", "decoder");
bin = gst_bin_new ("mybin");
gst_bin_add (GST_BIN (bin), element);
gst_element_add_ghost_pad (bin, gst_element_get_pad (element, "sink"), "sink");
</programlisting>
<para>
In the above example, the bin now also has a pad: the pad called 'sink' of the
given element. We can now, for example, connect the srcpad of a disksrc to the
bin with:
</para>
<programlisting>
GstElement *disksrc;
disksrc = gst_elementfactory_create ("disksrc", "disk_reader");
gst_element_connect (disksrc, "src", bin, "sink");
...
</programlisting>
</sect1>
</chapter>

59
docs/manual/buffers.xml Normal file
View file

@ -0,0 +1,59 @@
<chapter id="cha-buffers">
<title>Buffers</title>
<para>
Buffers contain the data that will flow through the pipeline you have created. A source
element will typically create a new buffer and pass it through the pad to the next
element in the chain.
When using the GStreamer infrastructure to create a media pipeline you will not have
to deal with buffers yourself; the elements will do that for you.
</para>
<para>
The most important information in the buffer is:
<itemizedlist>
<listitem>
<para>
A pointer to a piece of memory.
</para>
</listitem>
<listitem>
<para>
The size of the memory.
</para>
</listitem>
<listitem>
<para>
A refcount that indicates how many elements are using this buffer. This refcount
will be used to destroy the buffer when no element is having a reference to it.
</para>
</listitem>
</itemizedlist>
</para>
<para>
GStreamer provides functions to create custom buffer create/destroy algorithms, called
a <classname>GstBufferPool</classname>. This makes it possible to efficiently
allocate and destroy buffer memory. It also makes it possible to exchange memory between
elements by passing the <classname>GstBufferPool</classname>. A video element can,
for example, create a custom buffer allocation algorithm that creates buffers with XSHM
as the buffer memory. An element can use this algorithm to create and fill the buffer
with data.
</para>
<para>
The simple case is that a buffer is created, memory allocated, data put
in it, and passed to the next filter. That filter reads the data, does
something (like creating a new buffer and decoding into it), and
unreferences the buffer. This causes the data to be freed and the buffer
to be destroyed. A typical MPEG audio decoder works like this.
</para>
<para>
A more complex case is when the filter modifies the data in place. It
does so and simply passes on the buffer to the next element. This is just
as easy to deal with. An element that works in place has to be carefull when
the buffer is used in more than one element; a copy on write has to made in this
situation.
</para>
</chapter>

View file

@ -9,7 +9,7 @@
<title>Visualisation of three connected elements</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/connected-elements" format="PNG">
<imagedata fileref="images/connected-elements.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>

98
docs/manual/debugging.xml Normal file
View file

@ -0,0 +1,98 @@
<chapter id="cha-debugging">
<title>Debugging</title>
<para>
GStreamer has an extensive set of debugging tools for
plugin developers.
</para>
<sect1>
<title>Command line options</title>
<para>
Applications using the GStreamer libraries accept the following set
of command line argruments to enable the debugging system.
</para>
<para>
<itemizedlist>
<listitem>
<para>
<option>--gst-debug-mask=<replaceable>mask</replaceable></option>
Sets the mask for the debugging output.
</para>
</listitem>
<listitem>
<para>
<option>--gst-info-mask=<replaceable>mask</replaceable></option>
Sets the mask for the info output.
</para>
</listitem>
<listitem>
<para>
<option>--gst-mask=<replaceable>mask</replaceable></option>
Sets the mask for the info *and* the debug output.
</para>
</listitem>
<listitem>
<para>
<option>--gst-plugin-spew</option>
Enable printout of errors while loading GST plugins.
</para>
</listitem>
<listitem>
<para>
<option>--gst-plugin-path=<replaceable>PATH</replaceable></option>
Add a directory to the plugin search path.
</para>
</listitem>
<listitem>
<para>
<option>--help</option> Print the a short desciption of the
options and an overview of the current debugging/info masks
set.
</para>
</listitem>
</itemizedlist>
</para>
<para>
The follwing table gives an overview of the mask values and
their meaning. (enabled) means that the corresponding flag
has been set.
</para>
<programlisting>
Mask (to be OR'ed) info/debug FLAGS
--------------------------------------------------------
0x00000001 (enabled)/ GST_INIT
0x00000002 / COTHREADS
0x00000004 / COTHREAD_SWITCH
0x00000008 / AUTOPLUG
0x00000010 / AUTOPLUG_ATTEMPT
0x00000020 / PARENTAGE
0x00000040 / STATES
0x00000080 / PLANING
0x00000100 / SCHEDULING
0x00000200 / OPERATION
0x00000400 / BUFFER
0x00000800 / CAPS
0x00001000 / CLOCK
0x00002000 / ELEMENT_PADS
0x00004000 / ELEMENTFACTORY
0x00008000 / PADS
0x00010000 / PIPELINE
0x00020000 / PLUGIN_LOADING
0x00040000 / PLUGIN_ERRORS
0x00080000 / PLUGIN_INFO
0x00100000 / PROPERTIES
0x00200000 / THREAD
0x00400000 / TYPES
0x00800000 / XML
0x01000000 / NEGOTIATION
0x02000000 / REFCOUNTING
</programlisting>
</sect1>
<sect1>
<title>Adding a custom debug handler</title>
<para>
</para>
</sect1>
</chapter>

161
docs/manual/elements.xml Normal file
View file

@ -0,0 +1,161 @@
<chapter id="cha-elements">
<title>GstElement</title>
<para>
The most important object in <application>GStreamer</application> for the
application programmer is the <classname>GstElement</classname> object.
</para>
<sect1 id="sec-elements-design">
<title>What is a GstElement</title>
<para>
The GstElement is the basic building block for the media pipeline. All the
different components you are going to use are derived from this GstElement.
This means that a lot of functions you are going to use operate on this object.
</para>
<para>
You will see that those elements have pads. These are the elements
connections with the 'outside' world. Depending on the number and direction of
the pads, we can see three types of elements: source, filter and sink element.
</para>
<para>
These three types are all the same GstElement object, they just differ in how
the pads are.
</para>
<sect2 id="sec-elements-src">
<title>GStreamer source elements</title>
<para>
This element will generate data that will be used by the pipeline. It is
typically a file or an audio source.
</para>
<para>
Below you see how we will visualize the element.
We always draw a src pad to the right of the element.
</para>
<figure float="1" id="sec-element-srcimg">
<title>Visualisation of a source element</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/src-element.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
<para>
Source elements do not accept data, they only generate data. You can see
this in the figure because it only has a src pad. A src pad can only
generate buffers.
</para>
</sect2>
<sect2 id="sec-elements-filter">
<title>GStreamer filter elements</title>
<para>
Filter elements both have an input and an output pad. They operate on data
they receive in the sink pad and send the result to the src pad.
</para>
<para>
Examples of a filter element might include: an MPEG decoder, volume filter,...
</para>
<para>
Filters may also contain any number of input pads and output pads. For example,
a video mixer might have to input pads (the images of the two different video
streams) and one output pad.
</para>
<figure float="1" id="sec-element-filterimg">
<title>Visualisation of a filter element</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/filter-element.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
<para>
The above figure shows the visualisation of a filter element. This element has
one sink pad (input) and one src (output) pad. Sink pads are drawn on the left
of the element.
</para>
<figure float="1" id="sec-element-multifilterimg">
<title>Visualisation of a filter element with
more than one output pad</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/filter-element-multi.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
<para>
The above figure shows the visualisation of a filter element with more than one
output pad. An example of such a filter is the AVI splitter. This element will
parse the input data and extracts the audio and video data. Most of these filters
dynamically send out a signal when a new pad is created so that the application
programmer can connect an arbitrary element to the newly created pad.
</para>
</sect2>
<sect2 id="sec-elements-sink">
<title>GStreamer sink elements</title>
<para>
This element accepts data but will not generate any new data. A sink element
is typically a file on disk, a soundcard, a display,... It is presented as
below:
</para>
<figure float="1" id="sec-element-sinkimg">
<title>Visualisation of a sink element</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/sink-element.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
</sect2>
</sect1>
<sect1 id="sec-elements-create">
<title>Creating a GstElement</title>
<para>
GstElements are created from factories. To create an element, one has to get
access the a <classname>GstElementFactory</classname> using a unique factoryname.
</para>
<para>
The following code example is used to get a factory that can be used to create the
mpg123 element, an mp3 decoder.
</para>
<programlisting>
GstElementFactory *factory;
factory = gst_elementfactory_find ("mpg123");
</programlisting>
<para>
Once you have the handle to the elementfactory, you can create a real element with
the following code fragment:
</para>
<programlisting>
GstElement *element;
element = gst_elementfactory_create (factory, "decoder");
</programlisting>
<para>
gst_elementfactory_create () will use the elementfactory to create an element with the
given name. The name of the element is something you can use later on to lookup the
element in a bin, for example.
</para>
<para>
A simple shortcut exists for creating an element from a factory. The following example
creates an element, named "decoder" from the elementfactory named "mpg123". This
convenient function is most widly used to create an element.
</para>
<programlisting>
GstElement *element;
element = gst_elementfactory_make ("mpg123", "decoder");
</programlisting>
<para>
An element can be destroyed with:
</para>
<programlisting>
GstElement *element;
...
gst_element_destroy (element);
</programlisting>
</sect1>
</chapter>

332
docs/manual/factories.xml Normal file
View file

@ -0,0 +1,332 @@
<chapter id="cha-factories">
<title>More on factories</title>
<para>
The small application we created in the previous chapter used the
concept of a factory to create the elements. In this chapter we will
show you how to use the factory concepts to create elements based
on what they do instead of how they are called.
</para>
<para>
We will first explain the concepts involved before we move on
to the reworked helloworld example using autoplugging.
</para>
<sect1>
<title>The problems with the helloworld example</title>
<para>
If we take a look at how the elements were created in the previous
example we used a rather crude mechanism:
</para>
<programlisting>
...
/* now it's time to get the parser */
parse = gst_elementfactory_make ("mp3parse", "parse");
decoder = gst_elementfactory_make ("mpg123", "decoder");
...
</programlisting>
<para>
While this mechanism is quite effective it also has some big problems:
The elements are created based on their name. Indeed, we create an
element mpg123 by explicitly stating the mpg123 elements name.
Our little program therefore always uses the mpg123 decoder element
to decode the MP3 audio stream, even if there are 3 other MP3 decoders
in the system. We will see how we can use a more general way to create
an MP3 decoder element.
</para>
<para>
We have to introduce the concept of MIME types and capabilities
added to the source and sink pads.
</para>
</sect1>
<sect1>
<title>more on MIME Types</title>
<para>
GStreamer uses MIME types to indentify the different types of data
that can be handled by the elements. They are the high level
mechanisms to make sure that everyone is talking about the right
kind of data.
</para>
<para>
A MIME (Multipurpose Internet Mail Extension) types are a set of
string that denote a certain type of data. examples include:
<itemizedlist>
<listitem>
<para>
audio/raw : raw audio samples
</para>
</listitem>
<listitem>
<para>
audio/mpeg : mpeg audio
</para>
</listitem>
<listitem>
<para>
video/mpeg : mpeg video
</para>
</listitem>
</itemizedlist>
</para>
<para>
An element must associate a MIME type to its source and sink pads
when it is loaded into the system. GStreamer knows about the
different elements and what type of data they expect and emit.
This allows for very dynamic and extensible element creation as we
will see.
</para>
<para>
As we have seen in the previous chapter, the MIME types are added
to the Capability structure of a pad.
</para>
<para>
In our helloworld example the elements we constructed would have the
following MIME types associated with their source and sink pads:
</para>
<figure float="1" id="sec-mime-img">
<title>The Hello world pipeline with MIME types</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/mime-world.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
<para>
We will see how you can create an element based on the MIME types
of its source and sink pads. This way the end-user will have the
ability to choose his/her favorite audio/mpeg decoder without
you even having to care about it.
</para>
<para>
The typing of the source and sink pads also makes it possible to
'autoplug' a pipeline. We will have the ability to say: "construct
me a pipeline that does an audio/mpeg to audio/raw conversion".
</para>
<note>
<para>
The basic GStreamer library does not try to solve all of your
autoplug problems. It leaves the hard decisions to the application
programmer, where they belong.
</para>
</note>
</sect1>
<sect1>
<title>GStreamer types</title>
<para>
GStreamer assigns a unique number to all registered MIME types.
GStreamer also keeps a reference to
a function that can be used to determine if a given buffer is of
the given MIME type.
</para>
<para>
There is also an association between a MIME type and a file
extension.
</para>
<para>
The type information is maintained in a list of
<classname>GstType</classname>. The definition of a
<classname>GstType</classname> is like:
</para>
<programlisting>
typedef GstCaps (*GstTypeFindFunc) (GstBuffer *buf,gpointer *priv);
typedef struct _GstType GstType;
struct _GstType {
guint16 id; /* type id (assigned) */
gchar *mime; /* MIME type */
gchar *exts; /* space-delimited list of extensions */
GstTypeFindFunc typefindfunc; /* typefind function */
};
</programlisting>
<para>
All operations on <classname>GstType</classname> occur via their
<classname>guint16 id</classname> numbers, with <classname>GstType</classname>
structure private to the GStreamer library.
</para>
<sect2>
<title>MIME type to id conversion</title>
<para>
We can obtain the id for a given MIME type
with the following piece of code:
</para>
<programlisting>
guint16 id;
id = gst_type_find_by_mime ("audio/mpeg");
</programlisting>
<para>
This function will return 0 if the type was not known.
</para>
</sect2>
<sect2>
<title>id to <classname>GstType</classname> conversion</title>
<para>
We can obtain the <classname>GstType</classname> for a given id
with the following piece of code:
</para>
<programlisting>
GstType *type;
type = gst_type_find_by_id (id);
</programlisting>
<para>
This function will return NULL if the id was associated with
any known <classname>GstType</classname>
</para>
</sect2>
<sect2>
<title>extension to id conversion</title>
<para>
We can obtain the id for a given file extension
with the following piece of code:
</para>
<programlisting>
guint16 id;
id = gst_type_find_by_ext (".mp3");
</programlisting>
<para>
This function will return 0 if the extension was not known.
</para>
</sect2>
<sect2>
<title>id to <classname>GstElementFactory</classname> conversion</title>
<para>
When we have obtained a given type id using one of the above methods,
we can obtain a list of all the elements that operate on this MIME
type or extension.
</para>
<para>
Obtain a list of all the elements that use this id as source with:
</para>
<programlisting>
GList *list;
list = gst_type_gst_srcs (id);
</programlisting>
<para>
Obtain a list of all the elements that use this id as sink with:
</para>
<programlisting>
GList *list;
list = gst_type_gst_sinks (id);
</programlisting>
<para>
When you have a list of elements, you can simply take the first
element of the list to obtain an appropriate element.
</para>
<note>
<para>
As you can see, there might be a multitude of elements that
are able to operate on audio/raw types. some might include:
<itemizedlist>
<listitem>
<para>
an MP3 audio encoder.
</para>
</listitem>
<listitem>
<para>
an audio sink.
</para>
</listitem>
<listitem>
<para>
an audio resampler.
</para>
</listitem>
<listitem>
<para>
a spectrum filter.
</para>
</listitem>
</itemizedlist>
Depending on the application, you might want to use a different
element. This is why GStreamer leaves that decision up to the
application programmer.
</para>
</note>
</sect2>
<sect2>
<title>id to id path detection</title>
<para>
You can obtain a <classname>GList</classname> of elements that
will transform the source id into the destination id.
</para>
<programlisting>
GList *list;
list = gst_type_gst_sink_to_src (sourceid, sinkid);
</programlisting>
<para>
This piece of code will give you the elements needed to construct
a path from sourceid to sinkid. This function is mainly used in
autoplugging the pipeline.
</para>
</sect2>
</sect1>
<sect1>
<title>creating elements with the factory</title>
<para>
In the previous section we described how you could obtain
an element factory using MIME types. One the factory has been
obtained, you can create an element using:
</para>
<programlisting>
GstElementFactory *factory;
GstElement *element;
// obtain the factory
factory = ...
element = gst_elementfactory_create (factory, "name");
</programlisting>
<para>
This way, you do not have to create elements by name which
allows the end-user to select the elements he/she prefers for the
given MIME types.
</para>
</sect1>
<sect1>
<title>GStreamer basic types</title>
<para>
GStreamer only has two builtin types:
</para>
<itemizedlist>
<listitem>
<para>
audio/raw : raw audio samples
</para>
</listitem>
<listitem>
<para>
video/raw and image/raw : raw video data
</para>
</listitem>
</itemizedlist>
<para>
All other MIME types are maintained by the plugin elements.
</para>
</sect1>
</chapter>

View file

@ -1,34 +1,39 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
<!ENTITY INTRO SYSTEM "intro.sgml">
<!ENTITY MOTIVATION SYSTEM "motivation.sgml">
<!ENTITY GOALS SYSTEM "goals.sgml">
<?xml version='1.0'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % magic-entities SYSTEM "magic">
%magic-entities;
<!ENTITY INIT SYSTEM "init.sgml">
<!ENTITY ELEMENTS SYSTEM "elements.sgml">
<!ENTITY PADS SYSTEM "pads.sgml">
<!ENTITY CONNECTIONS SYSTEM "connections.sgml">
<!ENTITY BINS SYSTEM "bins.sgml">
<!ENTITY BUFFERS SYSTEM "buffers.sgml">
<!ENTITY STATES SYSTEM "states.sgml">
<!ENTITY INTRO SYSTEM "intro.xml">
<!ENTITY MOTIVATION SYSTEM "motivation.xml">
<!ENTITY GOALS SYSTEM "goals.xml">
<!ENTITY HELLOWORLD SYSTEM "helloworld.sgml">
<!ENTITY FACTORIES SYSTEM "factories.sgml">
<!ENTITY AUTOPLUGGING SYSTEM "autoplugging.sgml">
<!ENTITY HELLOWORLD2 SYSTEM "helloworld2.sgml">
<!ENTITY INIT SYSTEM "init.xml">
<!ENTITY ELEMENTS SYSTEM "elements.xml">
<!ENTITY PADS SYSTEM "pads.xml">
<!ENTITY CONNECTIONS SYSTEM "connections.xml">
<!ENTITY BINS SYSTEM "bins.xml">
<!ENTITY BUFFERS SYSTEM "buffers.xml">
<!ENTITY STATES SYSTEM "states.xml">
<!ENTITY THREADS SYSTEM "threads.sgml">
<!ENTITY QUEUES SYSTEM "queues.sgml">
<!ENTITY COTHREADS SYSTEM "cothreads.sgml">
<!ENTITY DYNAMIC SYSTEM "dynamic.sgml">
<!ENTITY TYPEDETECTION SYSTEM "typedetection.sgml">
<!ENTITY UTILITY SYSTEM "utility.sgml">
<!ENTITY HELLOWORLD SYSTEM "helloworld.xml">
<!ENTITY FACTORIES SYSTEM "factories.xml">
<!ENTITY AUTOPLUGGING SYSTEM "autoplugging.xml">
<!ENTITY HELLOWORLD2 SYSTEM "helloworld2.xml">
<!ENTITY XML SYSTEM "xml.sgml">
<!ENTITY PLUGINS SYSTEM "plugins.sgml">
<!ENTITY DEBUGGING SYSTEM "debugging.sgml">
<!ENTITY PROGRAMS SYSTEM "programs.sgml">
<!ENTITY COMPONENTS SYSTEM "components.sgml">
<!ENTITY QUOTES SYSTEM "quotes.sgml">
<!ENTITY THREADS SYSTEM "threads.xml">
<!ENTITY QUEUES SYSTEM "queues.xml">
<!ENTITY COTHREADS SYSTEM "cothreads.xml">
<!ENTITY DYNAMIC SYSTEM "dynamic.xml">
<!ENTITY TYPEDETECTION SYSTEM "typedetection.xml">
<!ENTITY UTILITY SYSTEM "utility.xml">
<!ENTITY XML SYSTEM "xml.xml">
<!ENTITY PLUGINS SYSTEM "plugins.xml">
<!ENTITY DEBUGGING SYSTEM "debugging.xml">
<!ENTITY PROGRAMS SYSTEM "programs.xml">
<!ENTITY COMPONENTS SYSTEM "components.xml">
<!ENTITY QUOTES SYSTEM "quotes.xml">
]>
<book id="index">

307
docs/manual/helloworld.xml Normal file
View file

@ -0,0 +1,307 @@
<chapter id="cha-hello">
<title>Your first application</title>
<para>
This chapter describes the most rudimentary aspects of a <application>GStreamer</application> application,
including initializing the libraries, creating elements, packing them into
a pipeline and playing, pause and stop the pipeline.
</para>
<sect1>
<title>Hello world</title>
<para>
We will create a simple first application. In fact it will be a complete
MP3 player, using standard <application>GStreamer</application> components. The player will read from
a file that is given as the first argument of the program.
</para>
<programlisting>
#include &lt;gst/gst.h&gt;
int
main (int argc, char *argv[])
{
GstElement *pipeline, *disksrc, *parse, *decoder, *audiosink;
gst_init(&amp;argc, &amp;argv);
if (argc != 2) {
g_print ("usage: &percnt;s &lt;filename&gt;\n", argv[0]);
exit (-1);
}
/* create a new pipeline to hold the elements */
pipeline = gst_pipeline_new ("pipeline");
/* create a disk reader */
disksrc = gst_elementfactory_make ("disksrc", "disk_source");
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
/* now it's time to get the parser */
parse = gst_elementfactory_make ("mp3parse", "parse");
decoder = gst_elementfactory_make ("mpg123", "decoder");
/* and an audio sink */
audiosink = gst_elementfactory_make ("osssink", "play_audio");
/* add objects to the main pipeline */
gst_bin_add (GST_BIN (pipeline), disksrc);
gst_bin_add (GST_BIN (pipeline), parse);
gst_bin_add (GST_BIN (pipeline), decoder);
gst_bin_add (GST_BIN (pipeline), audiosink);
/* connect src to sink */
gst_pad_connect (gst_element_get_pad (disksrc, "src"),
gst_element_get_pad (parse, "sink"));
gst_pad_connect (gst_element_get_pad (parse, "src"),
gst_element_get_pad (decoder, "sink"));
gst_pad_connect (gst_element_get_pad (decoder, "src"),
gst_element_get_pad (audiosink, "sink"));
/* start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
while (gst_bin_iterate (GST_BIN (pipeline)));
/* stop the pipeline */
gst_element_set_state (pipeline, GST_STATE_NULL);
/* we don't need a reference to these objects anymore */
gst_object_unref (GST_OBJECT (audiosink));
gst_object_unref (GST_OBJECT (parse));
gst_object_unref (GST_OBJECT (decoder));
gst_object_unref (GST_OBJECT (disksrc));
gst_object_unref (GST_OBJECT (pipeline));
exit (0);
}
</programlisting>
<para>
Let's go through this example step by step.
</para>
<para>
The first thing you have to do is to include the standard <application>GStreamer</application> headers and
initialize the framework.
</para>
<programlisting>
#include &lt;gst/gst.h&gt;
...
int
main (int argc, char *argv[])
{
...
gst_init(&amp;argc, &amp;argv);
...
</programlisting>
<para>
We are going to create 4 elements and one pipeline. Since all objects are
in fact elements, we can define them as:
</para>
<programlisting>
...
GstElement *pipeline, *disksrc, *parse, *decoder, *audiosink;
...
</programlisting>
<para>
Next, we are going to create an empty pipeline. As you have seen in the basic
introduction, this pipeline will hold and manage all the elements we are
going to stuff into it.
</para>
<programlisting>
/* create a new pipeline to hold the elements */
pipeline = gst_pipeline_new ("pipeline");
</programlisting>
<para>
We use the standard constructor for a pipeline: gst_pipeline_new ("name").
</para>
<para>
We then create a disk source element. The disk source element is able to
read from a file. We use the standard GObject property mechanism to set
a property of the element: the file to read from.
</para>
<programlisting>
/* create a disk reader */
disksrc = gst_elementfactory_make ("disksrc", "disk_source");
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
</programlisting>
<note>
<para>
You can check if the disksrc != NULL to verify the creation of the
disk source element.
</para>
</note>
<para>
We now create the MP3 decoder element. <application>GStreamer</application> requires you
to put a parser in front of the decoder. This parser will
cut the raw data from the disk source into MP3 frames
suitable for the decoder. In the advanced concepts chapter we will
see how this can be avoided.
</para>
<programlisting>
/* now it's time to get the parser */
parse = gst_elementfactory_make ("mp3parse", "parse");
decoder = gst_elementfactory_make ("mpg123", "decoder");
</programlisting>
<para>
gst_elementfactory_make() takes two arguments: a string that will
identify the element you need and a second argument: how you want
to name the element. The name of the element is something you can
choose yourself and might be used to retrieve the element from a
bin/pipeline.
</para>
<para>
Finally we create our audio sink element. This element will be able
to playback the audio using OSS.
</para>
<programlisting>
/* and an audio sink */
audiosink = gst_elementfactory_make ("audiosink", "play_audio");
</programlisting>
<para>
We then add the elements to the pipeline.
</para>
<programlisting>
/* add objects to the main pipeline */
gst_bin_add (GST_BIN (pipeline), disksrc);
gst_bin_add (GST_BIN (pipeline), parse);
gst_bin_add (GST_BIN (pipeline), decoder);
gst_bin_add (GST_BIN (pipeline), audiosink);
</programlisting>
<para>
We connect the different pads of the elements together like this:
</para>
<programlisting>
/* connect src to sink */
gst_pad_connect (gst_element_get_pad (disksrc, "src"),
gst_element_get_pad (parse, "sink"));
gst_pad_connect (gst_element_get_pad (parse, "src"),
gst_element_get_pad (decoder, "sink"));
gst_pad_connect (gst_element_get_pad (decoder, "src"),
gst_element_get_pad (audiosink, "sink"));
</programlisting>
<para>
We now have a created a complete pipeline. We can visualise the
pipeline as follows:
</para>
<figure float="1" id="sec-hello-img">
<title>The Hello world pipeline</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/hello-world.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
<para>
Everything is now set up to start the streaming. We use the following
statements to change the state of the pipeline:
</para>
<programlisting>
/* start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
</programlisting>
<note>
<para>
<application>GStreamer</application> will take care of the READY and PAUSED state for y
ou when going from NULL to PLAYING.
</para>
</note>
<para>
Since we do not use threads, nothing will happen yet. We manually have to
call gst_bin_iterate() to execute one iteration of the pipeline.
</para>
<programlisting>
while (gst_bin_iterate (GST_BIN (pipeline)));
</programlisting>
<para>
The gst_bin_iterate() function will return TRUE as long as something interesting
happended inside the pipeline. When the end-of-file has been reached the _iterate
function will return FALSE and we can end the loop.
</para>
<programlisting>
/* stop the pipeline */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (audiosink));
gst_object_unref (GST_OBJECT (decoder));
gst_object_unref (GST_OBJECT (disksrc));
gst_object_unref (GST_OBJECT (pipeline));
exit (0);
</programlisting>
<note>
<para>
don't forget to set the state of the pipeline to NULL. This will free
all of the resources held by the elements.
</para>
</note>
</sect1>
<sect1>
<title>compiling helloworld.c</title>
<para>
To compile the helloworld example, use:
</para>
<programlisting>
gcc -Wall `gstreamer-config --cflags --libs` helloworld.c \
-o helloworld
</programlisting>
<para>
This uses the program gstreamer-config, which comes with <application>GStreamer</application>. This program "knows"
what compiler switches are needed to compile programs that use <application>GStreamer</application>.
gstreamer-config --cflags will output a list of include
directories for the compiler to look in, and gstreamer-config --libs will output the
list of libraries for the compiler to link with and the directories to find them
in.
</para>
<para>
You can run the example with (substitute helloworld.mp3 with you favorite MP3 file):
</para>
<programlisting>
./helloworld helloworld.mp3
</programlisting>
</sect1>
<sect1>
<title>conclusion</title>
<para>
This concludes our first example. As you see, setting up a pipeline
is very lowlevel but powerfull. You will later in this manual how
you can create a custom MP3 element with a more high level API.
</para>
<para>
It should be clear from the example that we can very easily replace the
disksrc element with an httpsrc, giving you instant network streaming.
An element could be build to handle icecast connections, for example.
</para>
<para>
We can also choose to use another type of sink instead of the audiosink.
We could use a disksink to write the raw samples to a file, for example.
It should also be clear that inserting filters, like a stereo effect,
into the pipeline is not that hard to do. The most important thing is
that you can reuse allready existing elements.
</para>
</sect1>
</chapter>

View file

@ -0,0 +1,32 @@
<chapter id="cha-components">
<title>Components</title>
<para>
<application>GStreamer</application> includes components that people can include
in their programs.
</para>
<sect1>
<title>GstPlay</title>
<para>
GstPlay is a GtkWidget with a simple API to play, pause and stop a media file.
</para>
</sect1>
<sect1>
<title>GstMediaPlay</title>
<para>
GstMediaply is a complete player widget.
</para>
</sect1>
<sect1>
<title>GstEditor</title>
<para>
GstEditor is a set of widgets to display a graphical representation of a
pipeline.
</para>
</sect1>
</chapter>

49
docs/manual/intro.xml Normal file
View file

@ -0,0 +1,49 @@
<chapter id="cha-intro">
<title>Introduction</title>
<para>
This chapter gives you an overview of the technologies described in this
book.
</para>
<sect1 id="sec-intro-what">
<title>What is GStreamer?</title>
<para>
GStreamer is a framework for creating streaming media applications.
The fundamental design comes from the video pipeline at Oregon Graduate
Institute, as well as some ideas from DirectShow.
</para>
<para>
GStreamer's development framework makes it possible to write any
streaming multimedia application. The framework includes several
components to build a full featured media player capable of playing
MPEG1, MPEG2, AVI, MP3, WAV, AU, ...
</para>
<para>
GStreamer, however, is much more than just another media player. Its
main advantages are that the pluggable components also make it possible
to write a full flegded video or audio editing application.
</para>
<para>
The framework is based on plug-ins that will provide the various codec
and other functionality. The plugins can be connected and arranged in
a pipeline. This pipeline defines the flow of the data. Pipelines can
also be edited with a GUI editor and saved as XML so that pipeline
libraries can be made with a minimum of effort.
</para>
<para>
The GStreamer core function is to provide a framework for plugins, data flow
and media type handling/negotiation.
It also provides an API to write applications using the various plugins.
</para>
<para>
This book is about GStreamer from a developer's point of view; it describes
how to write a GStreamer application using the GStreamer libraries and tools.
</para>
</sect1>
</chapter>

1
docs/manual/magic-pdf Normal file
View file

@ -0,0 +1 @@
<!ENTITY magic "pdf">

1
docs/manual/magic-png Normal file
View file

@ -0,0 +1 @@
<!ENTITY magic "png">

View file

@ -0,0 +1,99 @@
<chapter id="cha-motivation">
<title>Motivation</title>
<para>
Linux has historically lagged behind other operating systems in the multimedia
arena. Microsoft's Windows[tm] and Apple's MacOS[tm] both have strong support
for multimedia devices, multimedia content creation,
playback, and realtime processing. Linux, on the other hand, has a poorly integrated
collection of multimedia utilities and applications available, which can hardly compete
with the professional level of software available for MS Windows and MacOS.
</para>
<sect1 id="sec-motivation-problems">
<title>Current problems</title>
<para>
We descibe the typical problems in todays media handling on Linux.
</para>
<sect2 id="sec-motivation-duplicate">
<title>Multitude of duplicate code</title>
<para>
The Linux user who wishes to hear a sound file must hunt through their collection of
sound file players in order to play the tens of sound file formats in wide use today.
Most of these players basically reimplement the same code over and over again.
</para>
<para>
The Linux developer who wishes to embed a video clip in their application must use
crude hacks to run an external video player. There is no library available that a
developer can use to create a custom media player.
</para>
</sect2>
<sect2 id="sec-motivation-goal">
<title>'One goal' media players/libraries</title>
<para>
Your typical MPEG player was designed to play MPEG video and audio. Most of
these players have implemented a complete infrastructure focused on
achieving their only goal: playback. No provisions were made to add
filters or special effects to the video or audio data.
</para>
<para>
If I wanted to convert an MPEG2 video stream into an AVI file, my best
option would be to take all of the MPEG2 decoding algorithms out
of the player and duplicate them into my own AVI encoder. These
algorithms cannot easily be shared accross applications.
</para>
<para>
Attempts have been made to create libraries for handling various media types.
Because they focus on a very specific media type (avifile, libmpeg2, ...),
significant work is needed to integrate them due to a lack of a common API.
GStreamer allows you to wrap these libraries with a common API, which
significantly simplifies integration and reuse.
</para>
</sect2>
<sect2 id="sec-motivation-plugin">
<title>Non unified plugin mechanisms</title>
<para>
Your typical media player might have a plugin for different media
types. Two media players will typically implement their own plugin
mechanism so that the codecs cannot be easily exchanged.
</para>
<para>
The lack of a unified plugin mechanism also seriously hinders the
creation of binary only codecs. No company is willing to port their
code to all the different plugin mechanisms.
</para>
<para>
While GStreamer also uses it own plugin system it offers a very rich
framework for the plugin developper and ensures the plugin can be used
in a wide range of applications, transparently interacting with other
plugins.
</para>
</sect2>
<sect2 id="sec-motivation-network">
<title>Provision for network transparency</title>
<para>
No infrastructure is present to allow network transparent media
handling. A distributed MPEG encoder will typically duplicate the
same encoder algorithms found in a non-distributed encoder.
</para>
<para>
No provisions have been made for emerging technologies such as
the GNOME object embedding using BONOBO.
</para>
</sect2>
<sect2 id="sec-motivation-catchup">
<title>Catch up with the Windows(tm) world</title>
<para>
We need solid media handling if we want to see Linux succeed on
the desktop.
</para>
<para>
We must clear the road for commercially backed codecs and multimedia
applications so that Linux can become an option for doing multimedia.
</para>
</sect2>
</sect1>
</chapter>

459
docs/manual/pads.xml Normal file
View file

@ -0,0 +1,459 @@
<chapter id="cha-pads">
<title>GstPad</title>
<para>
As we have seen in the previous chapter (GstElement), the pads are the elements
connections with the outside world.
</para>
<para>
The specific type of media that the element can handle will be exposed by the pads.
The description of this media type is done with capabilities (<classname>GstCaps</classname>)
</para>
<sect1 id="sec-pads-get">
<title>Getting pads from an element</title>
<para>
Once you have created an element, you can get one of its pads with:
</para>
<programlisting>
GstPad *srcpad;
...
srcpad = gst_element_get_pad (element, "src");
...
</programlisting>
<para>
This function will get the pad named "src" from the given element.
</para>
<para>
Alternatively, you can also request a GList of pads from the element. The following
code example will print the names of all the pads of an element.
</para>
<programlisting>
GList *pads;
...
pads = gst_element_get_pad_list (element);
while (pads) {
GstPad *pad = GST_PAD (pads-&gt;data);
g_print ("pad name &percnt;s\n", gst_pad_get_name (pad));
pads = g_list_next (pads);
}
...
</programlisting>
<sect2 id="sec-pads-functions">
<title>Useful pad functions</title>
<para>
You can get the name of a pad with gst_pad_get_name () and set its name with
get_pad_set_name();
</para>
<para>
gst_pad_get_direction (GstPad *pad) can be used to query if the pad is a sink
or a src pad. Remember a src pad is a pad that can output data and a sink pad is
one that accepts data.
</para>
<para>
You can get the parent of the pad, this is the element that this pad belongs to,
with get_pad_set_parent(GstPad *pad). This function will return a pointer to a
GstObject.
</para>
</sect2>
<sect2 id="sec-pads-dynamic">
<title>Dynamic pads</title>
<para>
Some elements might not have their pads when they are created. This can, for
example, happen with an MPEG2 system demuxer. The demuxer will create its
pads at runtime when it detects the different elementary streams in the MPEG2
system stream.
</para>
<para>
Running <application>gstreamer-inspect mpeg2parse</application> will show that
the element has only one pad: a sink pad called 'sink'. The other pads are
"dormant" as you can see in the padtemplates from the 'Exists: Sometimes'
property. Depending on the type of MPEG2 file you play, the pads are created. We
will see that this is very important when you are going to create dynamic
pipelines later on in this manual.
</para>
<para>
You can attach a signal to an element to inform you when the element has created
a new pad from one of its padtemplates. The following piece of code is an example
of how to do this:
</para>
<programlisting>
static void
pad_connect_func (GstElement *parser, GstPad *pad, GstElement *pipeline)
{
g_print("***** a new pad &percnt;s was created\n", gst_pad_get_name(pad));
gst_element_set_state (pipeline, GST_STATE_PAUSED);
if (strncmp (gst_pad_get_name (pad), "private_stream_1.0", 18) == 0) {
// set up an AC3 decoder pipeline
...
// connect pad to the AC3 decoder pipeline
...
}
gst_element_set_state (GST_ELEMENT (audio_thread), GST_STATE_READY);
}
int
main(int argc, char *argv[])
{
GstElement *pipeline;
GstElement *mpeg2parser;
// create pipeline and do something usefull
...
mpeg2parser = gst_elementfactory_make ("mpeg2parse", "mpeg2parse");
g_signal_connect (G_OBJECT (mpeg2parser), "new_pad", pad_connect_func, pipeline);
...
// start the pipeline
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
...
}
</programlisting>
<note>
<para>
You need to set the pipeline to READY or NULL if you want to change it.
</para>
</note>
</sect2>
<sect2 id="sec-pads-request">
<title>Request pads</title>
<para>
An element can also have request pads. These pads are not created automatically
but are only created on demand. This is very usefull for muxers, aggregators
and tee elements.
</para>
<para>
The tee element, for example, has one input pad and a request padtemplate for the
output pads. Whenever an element wants to get an output pad from the tee element, it
has to request the pad.
</para>
<para>
The following piece of code can be used to get a pad from the tee element. After
the pad has been requested, it can be used to connect another element to it.
</para>
<programlisting>
...
GstPad *pad;
...
element = gst_elementfactory_make ("tee", "element");
pad = gst_element_request_pad_by_name (element, "src%d");
g_print ("new pad %s\n", gst_pad_get_name (pad));
...
</programlisting>
<para>
The gst_element_request_pad_by_name method can be used to get a pad
from the element based on the name_template of the padtemplate.
</para>
<para>
It is also possible to request a pad that is compatible with another
padtemplate. This is very usefull if you want to connect an element to
a muxer element and you need to request a pad that is compatible. The
gst_element_request_compatible_pad is used to request a compatible pad, as
is shown in the next example.
</para>
<programlisting>
...
GstPadTemplate *templ;
GstPad *pad;
...
element = gst_elementfactory_make ("tee", "element");
mp3parse = gst_elementfactory_make ("mp3parse", "mp3parse");
templ = gst_element_get_padtemplate_by_name (mp3parse, "sink");
pad = gst_element_request_compatible_pad (element, templ);
g_print ("new pad %s\n", gst_pad_get_name (pad));
...
</programlisting>
</sect2>
</sect1>
<sect1 id="sec-pads-description">
<title>Capabilities of a GstPad</title>
<para>
Since the pads play a very important role in how the element is viewed by the
outside world, a mechanism is implemented to describe the pad by using capabilities.
</para>
<para>
We will briefly describe what capabilities are, enough for you to get a basic understanding
of the concepts. You will find more information on how to create capabilities in the
filter-writer-guide.
</para>
<sect2 id="sec-pads-caps">
<title>What is a capability</title>
<para>
A capability is attached to a pad in order to describe what type of media the pad
can handle.
</para>
<para>
A capability is named and consists of a MIME type and a set of properties. Its data
structure is:
</para>
<programlisting>
struct _GstCaps {
gchar *name; /* the name of this caps */
guint16 id; /* type id (major type) */
guint refcount; /* caps are refcounted */
GstProps *properties; /* properties for this capability */
GstCaps *next; /* caps can be chained together */
};
</programlisting>
<para>
Below is a dump of the capabilities of the element mpg123, as shown by
<command>gstreamer-inspect</command>.
You can see two pads: sink and src. Both pads have capability information attached to them.
</para>
<para>
The sink pad (input pad) is called 'sink' and takes data of MIME type 'audio/mp3'. It also has
three properties: layer, bitrate and framed.
</para>
<para>
The src pad (output pad) is called 'src' and outputs data of MIME type 'audio/raw'. It also has
four properties: format, depth, rate and channels.
</para>
<programlisting>
Pads:
SINK: 'sink'
....
Capabilities:
'mpg123_sink':
MIME type: 'audio/mp3':
layer: Integer range: 1 - 3
bitrate: Integer range: 8 - 320
framed: Boolean: TRUE
SRC: 'src'
....
Capabilities:
'mpg123_src':
MIME type: 'audio/raw':
format: Integer: 16
depth: Integer: 16
rate: Integer range: 11025 - 48000
channels: List:
Integer: 1
Integer: 2
</programlisting>
</sect2>
<sect2 id="sec-pads-props">
<title>What are properties</title>
<para>
Properties are used to describe extra information for the capabilities. The properties
basically exist of a key (a string) and a value. There are different possibile value types
that can be used:
</para>
<itemizedlist>
<listitem>
<para>
An integer value: the property has this exact value.
</para>
</listitem>
<listitem>
<para>
An integer range value. The property denotes a range of possible values. In the case
of the mpg123 element: the src pad has a property rate that can go from 11025 to 48000.
</para>
</listitem>
<listitem>
<para>
A boolean value.
</para>
</listitem>
<listitem>
<para>
a fourcc value: this is a value that is commonly used to describe an encoding for video,
as used be the AVI specification.
</para>
</listitem>
<listitem>
<para>
A list value: the property can take any value from a list.
</para>
</listitem>
<listitem>
<para>
A float value: the property has this exact floating point value.
</para>
</listitem>
<listitem>
<para>
A float range value: denotes a range of possible floating point values.
</para>
</listitem>
<listitem>
<para>
A string value.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="sec-pads-caps-use">
<title>What are the capabilities used for?</title>
<para>
Capabilities describe in great detail the type of media that is handled by the pads.
They are mostly used for:
</para>
<itemizedlist>
<listitem>
<para>
Autoplugging: automatically finding plugins for a set of capabilities
</para>
</listitem>
<listitem>
<para>
Compatibility detection: when two pads are connected, <application>GStreamer</application>
can verify if the two pads are talking about the same media types.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="sec-pads-caps-get">
<title>Getting the capabilities of a pad</title>
<para>
A pad can have a chain of capabilities attached to it. You can get the capabilities chain
with:
</para>
<programlisting>
GstCaps *caps;
...
caps = gst_pad_get_caps (pad);
g_print ("pad name &percnt;s\n", gst_pad_get_name (pad));
while (caps) {
g_print (" Capability name &percnt;s, MIME type &percnt;s\n",
gst_caps_get_name (cap),
gst_caps_get_mime (cap));
caps = caps-&gt;next;
}
...
</programlisting>
</sect2>
<sect2 id="sec-pads-caps-create">
<title>Creating capabilities structures</title>
<para>
While the capabilities are mainly used inside the plugin to describe the media type of the
pads, the application programmer also has to have basic understanding of caps in order to
interface with the plugins, specially when using the autopluggers.
</para>
<para>
As we said, a capability has a name, a mime-type and some properties. The signature of the
function to create a new <classname>GstCaps *</classname> structure is like:
<programlisting>
GstCaps* gst_caps_new (const gchar *name, const gchar *mime, GstProps *props);
</programlisting>
</para>
<para>
You can therefore create a new capability with no properties like this:
<programlisting>
GstCaps *newcaps;
newcaps = gst_caps_new ("my_caps", "audio/wav", NULL);
</programlisting>
</para>
<para>
<classname>GstProps</classname> basically consist of a set of key-value pairs
and are created with a function with this signature:
<programlisting>
GstProps* gst_props_new (const gchar *firstname, ...);
</programlisting>
</para>
<para>
The keys are given as strings and the values are given with a set of macros:
<itemizedlist>
<listitem>
<para>
GST_PROPS_INT(a): An integer value
</para>
</listitem>
<listitem>
<para>
GST_PROPS_FLOAT(a): A floating point value
</para>
</listitem>
<listitem>
<para>
GST_PROPS_FOURCC(a): A fourcc value
</para>
</listitem>
<listitem>
<para>
GST_PROPS_BOOLEAN(a): A boolean value
</para>
</listitem>
<listitem>
<para>
GST_PROPS_STRING(a): A string value
</para>
</listitem>
</itemizedlist>
The values can also be specified as ranges with:
<itemizedlist>
<listitem>
<para>
GST_PROPS_INT_RANGE(a,b): An integer ragne from a to b
</para>
</listitem>
<listitem>
<para>
GST_PROPS_FLOAT_RANGE(a,b): A float ragne from a to b
</para>
</listitem>
</itemizedlist>
All of the above values can be given with a list too, using:
<itemizedlist>
<listitem>
<para>
GST_PROPS_LIST(a,...): A list of property values.
</para>
</listitem>
</itemizedlist>
</para>
<para>
A more complex capability with properties is created like this:
<programlisting>
GstCaps *newcaps;
newcaps = gst_caps_new ("my_caps",
"audio/wav",
gst_props_new (
"bitrate", GST_PROPS_INT_RANGE (11025,22050),
"depth", GST_PROPS_INT (16),
"signed", GST_PROPS_LIST (
GST_PROPS_BOOLEAN (TRUE),
GST_PROPS_BOOLEAN (FALSE)
),
NULL
);
</programlisting>
Optionally the convenient shortcut macro can be used. The above complex
capability can be created with:
<programlisting>
GstCaps *newcaps;
newcaps = GST_CAPS_NEW ("my_caps",
"audio/wav",
"bitrate", GST_PROPS_INT_RANGE (11025,22050),
"depth", GST_PROPS_INT (16),
"signed", GST_PROPS_LIST (
GST_PROPS_BOOLEAN (TRUE),
GST_PROPS_BOOLEAN (FALSE)
)
);
</programlisting>
</para>
</sect2>
</sect1>
</chapter>

70
docs/manual/plugins.xml Normal file
View file

@ -0,0 +1,70 @@
<chapter id="cha-plugins">
<title>What are Plugins</title>
<para>
A plugin is a shared library that contains at least one of the following items:
</para>
<itemizedlist>
<listitem>
<para>
one or more elementfactories
</para>
</listitem>
<listitem>
<para>
one or more typedefinitions
</para>
</listitem>
<listitem>
<para>
one or more autopluggers
</para>
</listitem>
</itemizedlist>
<para>
The plugins have one simple method: plugin_init () where all the elementfactories are
created and the typedefinitions are registered.
</para>
<para>
the plugins are maintained in the plugin system. Optionally, the typedefinitions and
the elementfactories can be saved into an XML representation so that the plugin system
does not have to load all available plugins in order to know their definition.
</para>
<para>
The basic plugin structure has the following fields:
</para>
<programlisting>
struct _GstPlugin {
gchar *name; /* name of the plugin */
gchar *longname; /* long name of plugin */
gchar *filename; /* filename it came from */
GList *types; /* list of types provided */
gint numtypes;
GList *elements; /* list of elements provided */
gint numelements;
GList *autopluggers; /* list of autopluggers provided */
gint numautopluggers;
gboolean loaded; /* if the plugin is in memory */
};
</programlisting>
<para>
You can query a GList of available plugins with:
</para>
<programlisting>
GList *plugins;
plugins = gst_plugin_get_list ();
while (plugins) {
GstPlugin *plugin = (GstPlugin *)plugins-&gt;data;
g_print ("plugin: &percnt;s\n", gst_plugin_get_name (plugin));
plugins = g_list_next (plugins);
}
</programlisting>
</chapter>

240
docs/manual/programs.xml Normal file
View file

@ -0,0 +1,240 @@
<chapter id="cha-programs">
<title>Programs</title>
<para>
</para>
<sect1>
<title><command>gstreamer-config</command></title>
<para>
<command>gstreamer-config</command> is a script to get information about the installed
version of <application>GStreamer</application>.
This program "knows" what compiler switches are needed to compile programs that use
<application>GStreamer</application>.
</para>
<para>
<command>gstreamer-config</command> accepts the following options:
<itemizedlist>
<listitem>
<para>
<option>--version</option> Print the currently installed version of
<application>GStreamer</application> on the standard output.
</para>
</listitem>
<listitem>
<para>
<option>--libs</option> Print the linker flags that are necessary to link a
<application>GStreamer</application> program.
</para>
</listitem>
<listitem>
<para>
<option>--cflags</option> Print the compiler flags that are necessary to compile a
<application>GStreamer</application> program.
</para>
</listitem>
<listitem>
<para>
<option>--prefix=<replaceable>PREFIX</replaceable></option>
If specified, use <replaceable>PREFIX</replaceable> instead of the installation
prefix that <application>GStreamer</application> was built with when computing the
output for the <option>--cflags</option> and <option>--libs</option> options.
This option is also used for the exec prefix if
<option>--exec-prefix</option> was not specified. This option must be specified before any
<option>--libs</option> or <option>--cflags</option> options.
</para>
</listitem>
<listitem>
<para>
<option>--exec-prefix=<replaceable>PREFIX</replaceable></option>
If specified, use <replaceable>PREFIX</replaceable> instead of the installation exec
prefix that <application>GStreamer</application> was built with when computing the
output for the <option>--cflags</option> and <option>--libs</option> options. This option must be
specified before any <option>--libs</option> or <option>--cflags</option>
options.
</para>
</listitem>
</itemizedlist>
</para>
<para>
A simple <filename>Makefile</filename> will contain something like:
<programlisting>
CC = gcc
helloworld2: helloworld2.c
$(CC) -Wall `gstreamer-config --cflags --libs` helloworld2.c -o helloworld2
clean:
rm -f *.o helloworld2
</programlisting>
</para>
</sect1>
<sect1>
<title><command>gstreamer-register</command></title>
<para>
<command>gstreamer-register</command> is used to rebuild the database of plugins.
It is used after a new plugin has been added to the system. The plugin database
can be found in <filename>/etc/gstreamer/reg.xml</filename>.
</para>
</sect1>
<sect1>
<title><command>gstreamer-launch</command></title>
<para>
This is a tool that will construct pipelines based on a command-line
syntax.
</para>
<para>
A simple commandline looks like:
<screen>
gstreamer-launch disksrc location=hello.mp3 ! mp3parse ! mpg123 ! audiosink
</screen>
A more complex pipeline looks like:
<screen>
gstreamer-launch disksrc redpill.vob audio_00! (ac3parse ! ac3dec ! audiosink) \
video_00! (mpeg2dec ! videosink)
</screen>
</para>
<para>
Note that the parser isn't capable of more complex pipelines yet, including
the VOB player above. The minor tweaks will be made post 0.2.1.
</para>
<para>
You can also use the the parser in you own code. <application>GStreamer</application>
provides a function gst_parse_launch () that you can use to construt a pipeline.
The following programs lets you create an mp3 pipeline using the gst_parse_launch ()
function:
</para>
<programlisting>
#include &lt;gst/gst.h&gt;
int
main (int argc, char *argv[])
{
GstElement *pipeline;
GstElement *disksrc;
gst_init (&amp;argc, &amp;argv);
if (argc != 2) {
g_print ("usage: %s &lt;filename&gt;\n", argv[0]);
return -1;
}
pipeline = gst_pipeline_new ("my_pipeline");
gst_parse_launch ("disksrc[my_disksrc] ! mp3parse ! mpg123 ! osssink", GST_BIN (pipeline));
disksrc = gst_bin_get_by_name (GST_BIN (pipeline), "my_disksrc");
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
while (gst_bin_iterate (GST_BIN (pipeline)));
gst_element_set_state (pipeline, GST_STATE_NULL);
return 0;
}
</programlisting>
<para>
Note how we can retrieve the disksrc element from the constructed bin using the
element name.
</para>
</sect1>
<sect1>
<title><command>gstreamer-inspect</command></title>
<para>
This is a tool to query a plugin or an element about its properties.
</para>
<para>
To query the information about the element mpg123, you would specify:
</para>
<screen>
gstreamer-inspect mpg123
</screen>
<para>
Below is the output of a query for the audiosink element:
</para>
<screen>
Factory Details:
Long name: Audio Sink (OSS)
Class: Sink/Audio
Description: Output to a sound card via OSS
Version: 0.1.0
Author(s): Erik Walthinsen &lt;omega@cse.ogi.edu&gt;
Copyright: (C) 1999
Pad Templates:
SINK template: 'sink'
Exists: Always
Capabilities:
'audiosink_sink':
MIME type: 'audio/raw':
format: Integer: 16
depth: List:
Integer: 8
Integer: 16
rate: Integer range: 8000 - 48000
channels: Integer range: 1 - 2
Element Flags:
GST_ELEMENT_THREADSUGGESTED
no flags set
Element Implementation:
No loopfunc(), must be chain-based or not configured yet
Has change_state() function
Pads:
SINK: 'sink'
Implementation:
Has chainfunc(): 0x4001cde8
Has default eosfunc() gst_pad_eos_func()
Pad Template: 'sink'
Capabilities:
'audiosink_sink':
MIME type: 'audio/raw':
format: Integer: 16
depth: List:
Integer: 8
Integer: 16
rate: Integer range: 8000 - 48000
channels: Integer range: 1 - 2
Element Arguments:
GstAudioSink::mute: Boolean
GstAudioSink::format: Enum (default 16)
(8): 8 Bits
(16): 16 Bits
GstAudioSink::channels: Enum (default 2)
(1): Mono
(2): Stereo
GstAudioSink::frequency: Integer
</screen>
<para>
To query the information about a plugin, you would do:
</para>
<screen>
gstreamer-inspect gstelements
</screen>
</sect1>
<sect1>
<title><command>gstmediaplay</command></title>
<para>
A sample media player.
</para>
</sect1>
</chapter>

View file

@ -26,7 +26,7 @@
<title>a two-threaded decoder with a queue</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/queue" format="PNG">
<imagedata fileref="images/queue.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>

186
docs/manual/quotes.xml Normal file
View file

@ -0,0 +1,186 @@
<chapter id="cha-quotes">
<title>Quotes from the Developers</title>
<para>
As well as being a cool piece of software,
<application>GStreamer</application> is a lively project, with
developers from around the globe very actively contributing.
We often hang out on the #gstreamer IRC channel on
irc.openprojects.net: the following are a selection of amusing<footnote>
<para>No guarantee of sense of humour compatibility is given.</para>
</footnote> quotes from our conversations.
</para>
<variablelist>
<varlistentry>
<term>16 Feb 2001</term>
<listitem>
<para>
<emphasis>wtay:</emphasis>
I shipped a few commerical products to &gt;40000 people now but
GStreamer is way more exciting...
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>16 Feb 2001</term>
<listitem>
<para>
*
<emphasis>tool-man</emphasis>
is a gstreamer groupie
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>14 Jan 2001</term>
<listitem>
<para>
<emphasis>Omega:</emphasis>
did you run ldconfig? maybe it talks to init?
</para>
<para>
<emphasis>wtay:</emphasis>
not sure, don't think so...
I did run gstreamer-register though :-)
</para>
<para>
<emphasis>Omega:</emphasis>
ah, that did it then ;-)
</para>
<para>
<emphasis>wtay:</emphasis>
right
</para>
<para>
<emphasis>Omega:</emphasis>
probably not, but in case GStreamer starts turning into an OS, someone please let me know?
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>9 Jan 2001</term>
<listitem>
<para>
<emphasis>wtay:</emphasis>
me tar, you rpm?
</para>
<para>
<emphasis>wtay:</emphasis>
hehe, forgot &quot;zan&quot;
</para>
<para>
<emphasis>Omega:</emphasis>
?
</para>
<para>
<emphasis>wtay:</emphasis>
me tar&quot;zan&quot;, you ...
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>7 Jan 2001</term>
<listitem>
<para>
<emphasis>Omega:</emphasis>
that means probably building an agreggating, cache-massaging
queue to shove N buffers across all at once, forcing cache
transfer.
</para>
<para>
<emphasis>wtay:</emphasis>
never done that before...
</para>
<para>
<emphasis>Omega:</emphasis>
nope, but it's easy to do in gstreamer &lt;g&gt;
</para>
<para>
<emphasis>wtay:</emphasis>
sure, I need to rewrite cp with gstreamer too, someday :-)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>7 Jan 2001</term>
<listitem>
<para>
<emphasis>wtay:</emphasis>
GStreamer; always at least one developer is awake...
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>5/6 Jan 2001</term>
<listitem>
<para>
<emphasis>wtay:</emphasis>
we need to cut down the time to create an mp3 player down to
seconds...
</para>
<para>
<emphasis>richardb:</emphasis>
:)
</para>
<para>
<emphasis>Omega:</emphasis>
I'm wanting to something more interesting soon, I did the "draw an mp3
player in 15sec" back in October '99.
</para>
<para>
<emphasis>wtay:</emphasis>
by the time Omega gets his hands on the editor, you'll see a
complete audio mixer in the editor :-)
</para>
<para>
<emphasis>richardb:</emphasis>
Well, it clearly has the potential...
</para>
<para>
<emphasis>Omega:</emphasis>
Working on it... ;-)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>28 Dec 2000</term>
<listitem>
<para>
<emphasis>MPAA:</emphasis>
We will sue you now, you have violated oru IP rights!
</para>
<para>
<emphasis>wtay:</emphasis>
hehehe
</para>
<para>
<emphasis>MPAA:</emphasis>
How dare you laugh at us? We have lawyers! We have Congressmen! We have <emphasis>LARS</emphasis>!
</para>
<para>
<emphasis>wtay:</emphasis>
I'm so sorry your honor
</para>
<para>
<emphasis>MPAA:</emphasis>
Hrumph.
</para>
<para>
*
<emphasis>wtay</emphasis>
bows before thy
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>4 Jun 2001</term>
<listitem>
<para><emphasis>taaz:</emphasis> you witchdoctors and your voodoo mpeg2 black magic... </para>
<para><emphasis>omega_:</emphasis> um. I count three, no four different cults there &lt;g&gt; </para>
<para><emphasis>ajmitch:</emphasis> hehe </para>
<para><emphasis>omega_:</emphasis> witchdoctors, voodoo, black magic, </para>
<para><emphasis>omega_:</emphasis> and mpeg </para>
</listitem>
</varlistentry>
</variablelist>
</chapter>

View file

@ -54,10 +54,10 @@
<para>
You can set the following states to an element:
</para>
<informaltable pgwide=1 frame="none" role="enum">
<informaltable pgwide="1" frame="none" role="enum">
<tgroup cols="2">
<colspec colwidth="2*">
<colspec colwidth="8*">
<colspec colwidth="2*" />
<colspec colwidth="8*" />
<tbody>
<row>
<entry><literal>GST_STATE_NULL</literal></entry>

143
docs/manual/threads.xml Normal file
View file

@ -0,0 +1,143 @@
<chapter id="cha-threads">
<title>Threads</title>
<para>
GStreamer has support for multithreading throught the use of
the <classname>GstThread</classname> object. This object is in fact
a special <classname>GstBin</classname> that will become a thread when started.
</para>
<para>
To construct a new thread you will perform something like:
</para>
<programlisting>
GstElement *my_thread;
// create the thread object
my_thread = gst_thread_new ("my_thread");
g_return_if_fail (audio_thread != NULL);
// add some plugins
gst_bin_add (GST_BIN (my_thread), GST_ELEMENT (funky_src));
gst_bin_add (GST_BIN (my_thread), GST_ELEMENT (cool_effect));
// connect the elements here...
...
// start playing
gst_element_set_state (GST_ELEMENT (my_thread), GST_STATE_PLAYING);
</programlisting>
<para>
The above program will create a thread with two elements in it. As soon
as it is set to the PLAYING state, the thread will start to iterate.
</para>
<note>
<para>
A thread should normally contain a source element. Most often, the thread
is fed with data from a queue.
</para>
</note>
<para>
A thread will be visualised as below
</para>
<figure float="1" id="sec-threads-img">
<title>a thread</title>
<mediaobject>
<imageobject>
<imagedata fileref="images/thread.&magic;" format="&magic;" />
</imageobject>
</mediaobject>
</figure>
<para>
As an example we show the helloworld program using a thread.
</para>
<programlisting>
#include &lt;gst/gst.h&gt;
/* eos will be called when the src element has an end of stream */
void
eos (GstSrc *src, gpointer data)
{
GstThread *thread = GST_THREAD (data);
g_print ("have eos, quitting\n");
/* stop the bin */
gst_element_set_state (GST_ELEMENT (thread), GST_STATE_NULL);
gst_main_quit ();
}
int
main (int argc, char *argv[])
{
GstElement *disksrc, *audiosink;
GstElement *pipeline;
GstElement *thread;
if (argc != 2) {
g_print ("usage: &percnt;s &lt;filename&gt;\n", argv[0]);
exit (-1);
}
gst_init (&amp;argc, &amp;argv);
/* create a new thread to hold the elements */
thread = gst_thread_new ("thread");
g_assert (thread != NULL);
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new ("pipeline");
g_assert (pipeline != NULL);
/* create a disk reader */
disksrc = gst_elementfactory_make ("disksrc", "disk_source");
g_assert (disksrc != NULL);
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
g_signal_connect (G_OBJECT (disksrc), "eos",
G_CALLBACK (eos), thread);
/* and an audio sink */
audiosink = gst_elementfactory_make ("audiosink", "play_audio");
g_assert (audiosink != NULL);
/* add objects to the main pipeline */
gst_bin_add (GST_BIN (pipeline), disksrc);
gst_bin_add (GST_BIN (pipeline), audiosink);
/* automatically setup the pipeline */
if (!gst_pipeline_autoplug (GST_PIPELINE (pipeline))) {
g_print ("unable to handle stream\n");
exit (-1);
}
/* remove the source element from the pipeline */
gst_bin_remove (GST_BIN (pipeline), disksrc);
/* insert the source element in the thread, remember a thread needs at
least one source or connection element */
gst_bin_add (GST_BIN (thread), disksrc);
/* add the pipeline to the thread too */
gst_bin_add (GST_BIN (thread), GST_ELEMENT (pipeline));
/* start playing */
gst_element_set_state (GST_ELEMENT (thread), GST_STATE_PLAYING);
/* do whatever you want here, the thread will be playing */
...
gst_main ();
gst_pipeline_destroy (thread);
exit (0);
}
</programlisting>
</chapter>

292
docs/manual/xml.xml Normal file
View file

@ -0,0 +1,292 @@
<chapter id="cha-xml">
<title>XML in <application>GStreamer</application></title>
<para>
<application>GStreamer</application> uses XML to store and load
its pipeline definitions. XML is also used internally to manage the
plugin registry. The plugin registry is a file that contains the definition
of all the plugins <application>GStreamer</application> knows about to have
quick access to the specifics of the plugins.
</para>
<para>
We will show you how you can save a pipeline to XML and how you can reload that
XML file again for later use.
</para>
<sect1 id="sec-xml-write">
<title>Turning GstElements into XML</title>
<para>
We create a simple pipeline and save it to disk with gst_xml_write (). The following
code constructs an mp3 player pipeline with two threads and finaly writes it to disk.
use this program with one argument: the mp3 file on disk.
</para>
<programlisting>
#include &lt;stdlib.h&gt;
#include &lt;gst/gst.h&gt;
gboolean playing;
int
main (int argc, char *argv[])
{
GstElement *disksrc, *audiosink, *queue, *queue2, *parse, *decode;
GstElement *bin;
GstElement *thread, *thread2;
gst_init (&amp;argc,&amp;argv);
if (argc != 2) {
g_print ("usage: &percnt;s &lt;filename&gt;\n", argv[0]);
exit (-1);
}
/* create a new thread to hold the elements */
thread = gst_elementfactory_make ("thread", "thread");
g_assert (thread != NULL);
thread2 = gst_elementfactory_make ("thread", "thread2");
g_assert (thread2 != NULL);
/* create a new bin to hold the elements */
bin = gst_bin_new ("bin");
g_assert (bin != NULL);
/* create a disk reader */
disksrc = gst_elementfactory_make ("disksrc", "disk_source");
g_assert (disksrc != NULL);
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
queue = gst_elementfactory_make ("queue", "queue");
queue2 = gst_elementfactory_make ("queue", "queue2");
/* and an audio sink */
audiosink = gst_elementfactory_make ("audiosink", "play_audio");
g_assert (audiosink != NULL);
parse = gst_elementfactory_make ("mp3parse", "parse");
decode = gst_elementfactory_make ("mpg123", "decode");
/* add objects to the main bin */
gst_bin_add (GST_BIN (bin), disksrc);
gst_bin_add (GST_BIN (bin), queue);
gst_bin_add (GST_BIN (thread), parse);
gst_bin_add (GST_BIN (thread), decode);
gst_bin_add (GST_BIN (thread), queue2);
gst_bin_add (GST_BIN (thread2), audiosink);
gst_pad_connect (gst_element_get_pad (disksrc,"src"),
gst_element_get_pad (queue,"sink"));
gst_pad_connect (gst_element_get_pad (queue,"src"),
gst_element_get_pad (parse,"sink"));
gst_pad_connect (gst_element_get_pad (parse,"src"),
gst_element_get_pad (decode,"sink"));
gst_pad_connect (gst_element_get_pad (decode,"src"),
gst_element_get_pad (queue2,"sink"));
gst_pad_connect (gst_element_get_pad (queue2,"src"),
gst_element_get_pad (audiosink,"sink"));
gst_bin_add (GST_BIN (bin), thread);
gst_bin_add (GST_BIN (bin), thread2);
// write the bin to disk
xmlSaveFile ("xmlTest.gst", gst_xml_write (GST_ELEMENT (bin)));
exit (0);
}
</programlisting>
<para>
The most important line is:
</para>
<programlisting>
xmlSaveFile ("xmlTest.gst", gst_xml_write (GST_ELEMENT (bin)));
</programlisting>
<para>
gst_xml_write () will turn the given element into and xmlDocPtr that
can be saved with the xmlSaveFile () function found in the gnome-xml
package. The result is an XML file named xmlTest.gst.
</para>
<para>
The complete element hierarchy will be saved along with the inter element
pad connections and the element parameters. Future <application>GStreamer</application>
versions will also allow you to store the signals in the XML file.
</para>
</sect1>
<sect1 id="sec-xml-load">
<title>Loading a GstElement from an XML file</title>
<para>
Before an XML file can be loaded, you must create a GstXML object.
A saved XML file can then be loaded with the
gst_xml_parse_file (xml, filename, rootelement) method.
The root element can optionally left NULL. The following code example loads
the previously created XML file and runs it.
</para>
<programlisting>
#include &lt;stdlib.h&gt;
#include &lt;gst/gst.h&gt;
int
main(int argc, char *argv[])
{
GstXML *xml;
GstElement *bin;
gboolean ret;
gst_init (&amp;argc, &amp;argv);
xml = gst_xml_new ();
ret = gst_xml_parse_file(xml, "xmlTest.gst", NULL);
g_assert (ret == TRUE);
bin = gst_xml_get_element (xml, "bin");
g_assert (bin != NULL);
gst_element_set_state (bin, GST_STATE_PLAYING);
while (gst_bin_iterate(GST_BIN(bin)));
gst_element_set_state (bin, GST_STATE_NULL);
exit (0);
}
</programlisting>
<para>
gst_xml_get_element (xml, "name") can be used to get a specific element
from the XML file.
</para>
<para>
gst_xml_get_topelements (xml) can be used to get a list of all toplevel elements
in the XML file.
</para>
<para>
In addition to loading a file, you can also load a from a xmlDocPtr and
an in memory buffer using gst_xml_parse_doc and gst_xml_parse_memory
respectivily. both of these methods return a gboolean indicating success
or failure of the requested action.
</para>
</sect1>
<sect1 id="sec-xml-custom">
<title>Adding custom XML tags into the core XML data</title>
<para>
It is possible to add custom XML tags to the core XML created with
gst_xml_write. This feature can be used by an application to add more
information to the save plugins. the editor will for example insert
the position of the elements on the screen using the custom XML tags.
</para>
<para>
It is strongly suggested to save and load the custom XML tags using
a namespace. This will solve the problem of having your XML tags
interfere with the core XML tags.
</para>
<para>
To insert a hook into the element saving procedure you can connect
a signal to the GstElement using the following piece of code:
</para>
<programlisting>
xmlNsPtr ns;
...
ns = xmlNewNs (NULL, "http://gstreamer.net/gst-test/1.0/", "test");
...
thread = gst_elementfactory_make ("thread", "thread");
g_signal_connect (G_OBJECT (thread), "object_saved",
G_CALLBACK (object_saved), g_strdup ("decoder thread"));
...
</programlisting>
<para>
When the thread is saved, the object_save method will be caled. Our example
will insert a comment tag:
</para>
<programlisting>
static void
object_saved (GstObject *object, xmlNodePtr parent, gpointer data)
{
xmlNodePtr child;
child = xmlNewChild (parent, ns, "comment", NULL);
xmlNewChild (child, ns, "text", (gchar *)data);
}
</programlisting>
<para>
Adding the custom tag code to the above example you will get an XML file
with the custom tags in it. Here's an excerpt:
</para>
<programlisting>
...
&lt;gst:element&gt;
&lt;gst:name&gt;thread&lt;/gst:name&gt;
&lt;gst:type&gt;thread&lt;/gst:type&gt;
&lt;gst:version&gt;0.1.0&lt;/gst:version&gt;
...
&lt;/gst:children&gt;
&lt;test:comment&gt;
&lt;test:text&gt;decoder thread&lt;/test:text&gt;
&lt;/test:comment&gt;
&lt;/gst:element&gt;
...
</programlisting>
<para>
To retrieve the custom XML again, you need to attach a signal to
the GstXML object used to load the XML data. You can then parse your
custom XML from the XML tree whenever an object is loaded.
</para>
<para>
We can extend our previous example with the following piece of
code.
</para>
<programlisting>
xml = gst_xml_new ();
g_signal_connect (G_OBJECT (xml), "object_loaded",
G_CALLBACK (xml_loaded), xml);
ret = gst_xml_parse_file (xml, "xmlTest.gst", NULL);
g_assert (ret == TRUE);
</programlisting>
<para>
Whenever a new object has been loaded, the xml_loaded function will be
called. this function looks like:
</para>
<programlisting>
static void
xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data)
{
xmlNodePtr children = self-&gt;xmlChildrenNode;
while (children) {
if (!strcmp (children-&gt;name, "comment")) {
xmlNodePtr nodes = children-&gt;xmlChildrenNode;
while (nodes) {
if (!strcmp (nodes-&gt;name, "text")) {
gchar *name = g_strdup (xmlNodeGetContent (nodes));
g_print ("object %s loaded with comment '%s'\n",
gst_object_get_name (object), name);
}
nodes = nodes-&gt;next;
}
}
children = children-&gt;next;
}
}
</programlisting>
<para>
As you can see, you'll get a handle to the GstXML object, the
newly loaded GstObject and the xmlNodePtr that was used to create
this object. In the above example we look for our special tag inside
the XML tree that was used to load the object and we print our
comment to the console.
</para>
</sect1>
</chapter>

View file

@ -1,107 +1,98 @@
# Included by directories containing manuals.
# Expects the following to be defined:
# manualname
# htmlname
# sgml_files
# fig_files
# eps_files
# png_files
PDFFILES=$(manualname).pdf
PSFILES=$(manualname).ps
# taken from selfdocbookx, http://cyberelk.net/tim/docbook/selfdocbookx/index.html
if HAVE_FIG2DEV_PNG
PNGS_TO_MAKE=$(png_files)
else
PNGS_TO_MAKE=
endif
# modified by andy wingo <apwingo@eos.ncsu.edu> 14 dec 2001 for use by gstreamer
$(manualname)/$(htmlname): $(sgml_files) $(PNGS_TO_MAKE)
if HAVE_DB2HTML
db2html $(manualname).sgml
else
@echo "Can't build $@: don't have db2html tool"
endif
all: html ps pdf
$(manualname).pdf: $(manualname).ps
if HAVE_PS2PDF
@if [ -r $< ] ; then ps2pdf $< $@ ; fi
else
@echo "Can't build $@: don't have ps2pdf tool"
endif
if HAVE_XSLTPROC
if HAVE_FIG2DEV_EPS
$(manualname).ps: $(sgml_files) $(eps_files)
else
$(manualname).ps: $(sgml_files)
endif
if HAVE_DB2PS
@if [ -r $< ] ; then db2ps $(manualname).sgml ; fi
else
@echo "Can't build $@: don't have db2ps tool"
endif
if HAVE_FIG2DEV_PNG
html: $(DOC)
else !HAVE_FIG2DEV_PNG
html:
endif !HAVE_FIG2DEV_PNG
images :
mkdir images
if HAVE_FIG2DEV_PDF
if HAVE_PDFXMLTEX
pdf: $(DOC).pdf
if HAVE_FIG2DEV_PNG
images/%.png : %.fig images
fig2dev -L png -s 16 $< $@
endif
if HAVE_PDFTOPS
ps: $(DOC).ps
else !HAVE_PDFTOPS
ps:
endif !HAVE_PDFTOPS
if HAVE_FIG2DEV_EPS
images/%.eps : %.fig images
fig2dev -L eps -s 16 -m 0.5 $< $@
endif
else !HAVE_PDFXMLTEX
pdf:
ps:
endif !HAVE_PDFXMLTEX
$(manualname)/images:
@if [ -d $(manualname) ] ; then \
if [ -d images ] ; then \
ln -sf ../images $(manualname)/images ;\
fi \
fi
else !HAVE_FIG2DEV_PDF
pdf:
ps:
endif !HAVE_FIG2DEV_PDF
htmldocs: $(manualname)/$(htmlname) $(manualname)/images
pdfdocs: $(PDFFILES)
psdocs: $(PSFILES)
else !HAVE_XSLTPROC
html:
ps:
pdf:
endif !HAVE_XSLTPROC
# Data to install, in the usual automake way
docdatadir = $(datadir)/gstreamer
docdata_DATA = $(PDFFILES) $(PSFILES)
$(DOC).fo: $(XML) $(PDFS) $(XSLFO) $(XSLFOMODS)
cp magic-pdf magic
xsltproc $(XSLFO) $(MAIN) > $@-t
mv -f $@-t $@
htmlinst: htmldocs
@if [ -r $(manualname)/$(htmlname) ] ; then \
echo "Installing $(manualname)" ; \
$(mkinstalldirs) $(DESTDIR)$(docdatadir)/$(manualname) ; \
$(mkinstalldirs) $(DESTDIR)$(docdatadir)/$(manualname)/images ; \
$(INSTALL_DATA) $(manualname)/*.html $(DESTDIR)$(docdatadir)/$(manualname) ; \
for a in "x" $(png_files); do \
if [ "x$$a" != "xx" ] ; then \
if [ -r $$a ] ; then \
$(INSTALL_DATA) $$a $(DESTDIR)$(docdatadir)/$(manualname)/images ; \
fi; fi; done \
else \
if [ -r $(srcdir)/$(manualname)/$(htmlname) ] ; then \
echo "Installing $(srcdir)/$(manualname)" ; \
$(mkinstalldirs) $(DESTDIR)$(docdatadir)/$(manualname) ; \
$(mkinstalldirs) $(DESTDIR)$(docdatadir)/$(manualname)/images ; \
$(INSTALL_DATA) $(srcdir)/$(manualname)/*.html $(DESTDIR)$(docdatadir)/$(manualname) ; \
for a in "x" $(png_files); do \
if [ "x$$a" != "xx" ] ; then \
if [ -r $$a ] ; then \
$(INSTALL_DATA) $$a $(DESTDIR)$(docdatadir)/$(manualname)/images ; \
fi; fi; done \
else \
echo "NOT installing HTML documentation: not present, and can't generate" ; \
fi \
fi
$(DOC).pdf: $(DOC).fo
pdfxmltex $<
pdfxmltex $<
htmluninst:
$(RM) -rf $(DESTDIR)$(docdatadir)/$(manualname)
$(DOC).ps: $(DOC).pdf
pdftops $< $@
all-local: htmldocs pdfdocs psdocs
clean-local:
$(RM) -rf $(manualname)/ $(manualname).junk/ images/*.eps images/*.png *.eps *.png *.ps *.pdf *.aux *.dvi *.log *.tex DBTOHTML_OUTPUT_DIR*
install-data-local: htmlinst
uninstall-local: htmluninst
$(DOC): $(XML) $(PNGS) $(XSLHTML) $(XSLHTMLMODS)
-$(RM) *.html
-$(RM) -r $@
mkdir $@
cp magic-png magic
xsltproc $(XSLHTML) $(MAIN)
mv *.html $@
cp -a $(STYLESHEET_IMAGES) $@/stylesheet-images
cp $(CSS) $@
test "x$(PNGS)" != "x" && mkdir $@/images && cp $(PNGS) $@/images || true
builddate:
echo -n $$(date "+%e %B %Y") > $@
clean:
-$(RM) -f *.log *.dvi *.aux *.tex *.out *-t
-$(RM) -f $(PNGS) $(PDFS) builddate *.html
-$(RM) -rf $(DOC) $(DOC).ps $(DOC).pdf $(DOC).fo
distclean: clean
-$(RM) -f *~ $(DOC).tar.gz docbook.tar.gz
# -$(RM) -r docbook
$(DOC).tar.gz: distclean
(cd ..; tar zcf /tmp/$(DOC).tar.gz $(DOC) )
mv /tmp/$(DOC).tar.gz .
#docbook: $(DOC).tar.gz all
# -$(RM) -r $@
# mkdir $@
# cp $(DOC).tar.gz $(DOC).ps $(DOC).pdf $@
# tar cf - $(DOC) | (cd $@; tar xf -)
#docbook.tar.gz: docbook
# tar zcf docbook.tar.gz docbook
# Make png from xfig
%.png: %.fig
fig2dev -Lpng $< $@
# Make pdf from xfig
%.pdf: %.fig
fig2dev -Lpdf $< $@
.PHONY: distclean clean all builddate

11
docs/xsl/admon.xsl Normal file
View file

@ -0,0 +1,11 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version='1.0'>
<!-- Turn on admonition graphics. -->
<xsl:param name="admon.graphics" select="'1'"/>
<xsl:param name="admon.graphics.path" select="'stylesheet-images/'"/>
</xsl:stylesheet>

10
docs/xsl/css.xsl Normal file
View file

@ -0,0 +1,10 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version='1.0'>
<!-- Use an HTML CSS stylesheet. -->
<xsl:param name="html.stylesheet" select="'base.css'"/>
</xsl:stylesheet>

11
docs/xsl/fileext.xsl Normal file
View file

@ -0,0 +1,11 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version='1.0'>
<!-- This sets the extension for HTML files to ".html". -->
<!-- (The stylesheet's default for XHTML files is ".xhtm".) -->
<xsl:param name="html.ext" select="'.html'"/>
</xsl:stylesheet>

16
docs/xsl/fo.xsl Normal file
View file

@ -0,0 +1,16 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<!-- This file is for customizing the default XSL stylesheets. -->
<!-- We include them here (this one is for print output): -->
<xsl:import
href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/>
<!-- .. and customize them here: -->
<xsl:include href="ulink.xsl"/>
<xsl:include href="keycombo.xsl"/>
</xsl:stylesheet>

18
docs/xsl/html.xsl Normal file
View file

@ -0,0 +1,18 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<!-- This file is for customizing the default XSL stylesheets. -->
<!-- We include them here (this one is for HTML output): -->
<xsl:import
href="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl"/>
<!-- .. and customize them here: -->
<xsl:include href="fileext.xsl"/>
<xsl:include href="keycombo.xsl"/>
<xsl:include href="admon.xsl"/>
<xsl:include href="css.xsl"/>
</xsl:stylesheet>

26
docs/xsl/keycombo.xsl Normal file
View file

@ -0,0 +1,26 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version='1.0'>
<!-- There is a bug in docbook-xsl-1.45; work around it here. -->
<!-- Also change it slightly for emacs key descriptions. -->
<xsl:template match="keycombo">
<xsl:variable name="action" select="@action"/>
<xsl:variable name="joinchar">
<xsl:choose>
<xsl:when test="$action='seq'"><xsl:text> </xsl:text></xsl:when>
<xsl:when test="$action='simul'">-</xsl:when>
<xsl:otherwise>-</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:for-each select="./*">
<xsl:if test="position()>1">
<xsl:value-of select="$joinchar"/>
</xsl:if>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

32
docs/xsl/ulink.xsl Normal file
View file

@ -0,0 +1,32 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version='1.0'>
<!-- This alters the rendering of URLs. Let's follow RFC 2396 -->
<!-- guidelines. -->
<xsl:template match="ulink">
<fo:basic-link external-destination="{@url}"
xsl:use-attribute-sets="xref.properties">
<xsl:choose>
<xsl:when test="count(child::node())=0">
<xsl:text>&lt;</xsl:text>
<xsl:value-of select="@url"/>
<xsl:text>&gt;</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</fo:basic-link>
<xsl:if test="count(child::node()) != 0">
<fo:inline hyphenate="false">
<xsl:text> at &lt;</xsl:text>
<xsl:value-of select="@url"/>
<xsl:text>&gt;</xsl:text>
</fo:inline>
</xsl:if>
</xsl:template>
</xsl:stylesheet>