xine-lib provides a portable API to a set of multimedia playback functions. It is the backbone of many free video and audio players, such as xine, gxine, Totem and Miro, but documentation for it is pretty thin on the ground.
This tutorial is intended to give a brief introduction to using xine-lib in your own applications, to play audio streams.
To use the examples below, make sure that you have xine-lib installed; if you're using Linux, then it's likely that your distribution will have a pre-compiled package available for you - make sure that you also install the development package which contains the C header files (under Debian Linux, this package is libxine-dev).
Before we can play any audio, we must first create a xine engine with
xine_new() and then initialise it with the
xine_init() function:
#include <xine.h>
...
xine_t ∗engine;
engine = xine_new();
xine_init(engine);
These two functions take care of malloc'ing the space for the
xine_t structure, initialising it, and then determining which plugins are available for xine to use.
Next, open an audio driver, with
xine_open_audio_driver(). This function takes three arguments; a pointer to the engine, the id of the driver and pointer to a structure used for communications between the user interface and the driver; set these both to NULL, and xine will instead auto-detect the driver to be used, which is what I'll do below. I can get away with it in this instance, because it's just a very simple application and my computer only has a single soundcard; a full-featured program should give the user the option of selecting their own driver and soundcard.
xine_audio_port_t ∗ap;
ap = xine_open_audio_driver(engine, NULL, NULL);
We also have to open a video driver; since we're only dealing with audio streams, we will set the video driver 'flavour' selector to
XINE_VISUAL_TYPE_NONE - in other words, no video driver. We use
xine_open_video_driver() for this:
xine_video_port_t ∗vp;
vp = xine_open_video_driver(engine, NULL, XINE_VISUAL_TYPE_NONE, NULL);
Now, we need to create a new stream and associate it with our xine engine, our audio driver and our (null) video driver. This is done with
xine_stream_new():
xine_stream_t ∗stream;
stream = xine_stream_new(engine, ap, vp);
Then we give the address of the audio that we want to listen to with the stream object; this address must be a direct link to the stream, not a playlist such as m3u, pls or asx files, as xine-lib is not able to parse them itself:
char ∗mrl="mms://whatever.wherever:80/";
xine_open(stream,mrl);
Note that the mrl doesn't have to be an audio stream on a network; it could also be a file on the disk:
char ∗mrl="/var/tmp/a_random_song.mp3";
The final step now is to play the audio, which we do with
xine_play(). It takes three arguments - the stream object itself, a start position (0-65535) and a start time, in milliseconds. Obviously it doesn't make sense to supply both a start position and a start time (and if you do this, then only the start position will be used). For streams that aren't seekable (for example, live audio streams), these two parameters will be ignored.
In our example here, we'll play the audio stream from the start:
xine_play(stream,0,0);
At this point, the stream should be playing through the system's sound
card. Playback is handled by a separate thread, so your main thread
can perform other tasks while it does this. For simplicity's sake, our
demonstration program just sleeps for ten minutes; when the sleep finishes,
it will stop any playback thread that is still running and then exit.
The full program is here:
#include <unistd.h>
#include <stdlib.h>
#include <xine.h>
#define MRL "http://dradio-live.ogg.t-bn.de/dlf_low.ogg#demux:ogg"
int main(int argc, char ∗∗argv)
{
char ∗mrl = MRL;
xine_t ∗engine; // Main libxine object
xine_audio_port_t ∗ap; // The audio driver
xine_video_port_t ∗vp; // The video driver
xine_stream_t ∗stream; // Stream object
// Create our libxine engine, and initialise it
engine = xine_new();
xine_init(engine);
// Automatically choose an audio driver
ap = xine_open_audio_driver(engine, NULL, NULL);
// We don't need a video driver
vp = xine_open_video_driver(engine, NULL, XINE_VISUAL_TYPE_NONE, NULL);
// Create a new stream object
stream = xine_stream_new(engine, ap, vp);
// Open the stream we want to listen to
xine_open(stream, mrl);
// Play the stream
xine_play(stream, 0, 0);
// Sleep for ten minutes, while playback goes on in a separate
// thread
sleep(10 ∗ 60);
// Stop playing and close down the stream
xine_close(stream);
// Now shut down cleanly
xine_close_audio_driver(engine, ap);
xine_close_video_driver(engine, vp);
xine_exit(engine);
exit(0);
}
The following Makefile will build it:
CFLAGS = -Wall
LDFLAGS = -lxine
all: xinedemo1
xinedemo1.o: xinedemo1.c
clean:
rm -rf ∗.o xinedemo1
The source code and Makefile can be downloaded
here. Compile the program up and run it without any arguments; once the stream
has buffered, you'll hear the audio playing:
./xinedemo1
This brings us to the end of this introductory tutorial; in the next article,
we'll look at xine-lib's event handling.
Should anyone be interested in writing their own audio player (and surprisingly enough, I've found the need to do so on more than one occasion), I've started writing a tutorial on using xine-lib. It's a great little library, but there's next-to-no documen
Tracked: Jan 03, 09:47