mirror of
https://code.videolan.org/videolan/vlc
synced 2024-10-03 01:31:53 +02:00
335 lines
14 KiB
XML
335 lines
14 KiB
XML
<chapter> <title> VLC interface </title>
|
|
|
|
<sect1> <title> A typical VLC run course </title>
|
|
|
|
<para>
|
|
This section describes what happens when you launch the <application>
|
|
vlc</application>
|
|
program. After the ELF dynamic loader blah blah blah, the main thread
|
|
becomes the interface thread and starts up in <filename>
|
|
src/interface/main.c </filename>. It passes through the following steps :
|
|
</para>
|
|
|
|
<orderedlist>
|
|
<listitem> <para> CPU detection : which CPU are we running on, what are
|
|
its capabilities (MMX, MMXEXT, 3DNow, AltiVec...) ? </para> </listitem>
|
|
<listitem> <para> Message interface initialization ; </para> </listitem>
|
|
<listitem> <para> Command line options parsing ; </para> </listitem>
|
|
<listitem> <para> Playlist creation ; </para> </listitem>
|
|
<listitem> <para> Module bank initialization ; </para> </listitem>
|
|
<listitem> <para> Interface opening ; </para> </listitem>
|
|
<listitem> <para> Signal handler installation : SIGHUP, SIGINT
|
|
and SIGQUIT are caught to manage a clean quit (please note that the SDL
|
|
library also catches SIGSEGV) ; </para> </listitem>
|
|
<listitem> <para> Audio output thread spawning ; </para> </listitem>
|
|
<listitem> <para> Video output thread spawning ; </para> </listitem>
|
|
<listitem> <para> Main loop : events management ; </para> </listitem>
|
|
</orderedlist>
|
|
|
|
<para>
|
|
Following sections describe each of these steps in particular, and many more.
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> The message interface </title>
|
|
|
|
<para>
|
|
It is a know fact that <function> printf() </function> functions are
|
|
not necessarily thread-safe. As a result,
|
|
one thread interrupted in a <function> printf() </function> call, followed
|
|
by another calls to it, will leave the program in an undetermined state. So
|
|
an API must be set up to print messages without crashing.
|
|
</para>
|
|
|
|
<para>
|
|
This API is implemented in two ways. If <constant> INTF_MSG_QUEUE </constant>
|
|
is defined in <filename> config.h </filename>, every <function>
|
|
printf</function>-like (see below) call will queue the message into a chained list.
|
|
This list will be printed and flushed by the interface thread once upon
|
|
an event loop. If <constant> INTF_MSG_QUEUE </constant> is undefined,
|
|
the calling thread will acquire the print lock (which prevents two
|
|
print operations to occur at the same time) and print the message
|
|
directly (default behaviour).
|
|
</para>
|
|
|
|
<para>
|
|
Functions available to print messages are :
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem> <para> <function> intf_Msg </function> ( <parameter>
|
|
char * psz_format, ... </parameter> ) :
|
|
Print a message to <constant> stdout </constant>, plain and
|
|
stupid (for instance "vlc 0.2.72 (Apr 16 2001)"). </para> </listitem>
|
|
|
|
<listitem> <para> <function> intf_ErrMsg </function> ( <parameter>
|
|
char * psz_format, ... </parameter> ) :
|
|
Print an error message to <constant> stderr </constant>. </para>
|
|
</listitem>
|
|
|
|
<listitem> <para> <function> intf_WarnMsg </function> ( <parameter>
|
|
int i_level, char * psz_format, ... </parameter> ) :
|
|
Print a message to <constant> stderr </constant> if the warning
|
|
level (determined by -v, -vv and -vvv) is low enough. </para>
|
|
<note> <para> Please note
|
|
that the lower the level, the less important the message is (dayou
|
|
spik ingliche ?). </para> </note> </listitem>
|
|
|
|
<listitem> <para> <function> intf_DbgMsg </function> ( <parameter>
|
|
char * psz_format, ... </parameter> ) :
|
|
This function is designed for optional checkpoint messages, such
|
|
as "we are now entering function dvd_foo_thingy". It does nothing
|
|
in non-trace mode. If the VLC is compiled with --enable-trace, the
|
|
message is either written to the file <filename> vlc-trace.log </filename>
|
|
(if TRACE_LOG is defined in config.h), or printed to <constant> stderr
|
|
</constant> (otherwise). </para> </listitem>
|
|
|
|
<listitem> <para> <function> intf_MsgImm, intf_ErrMsgImm, intf_WarnMsgImm,
|
|
intf_DbgMsgImm </function> :
|
|
Same as above, except that the message queue, in case <parameter>
|
|
INTF_MSG_QUEUE </parameter> is defined,
|
|
will be flushed before the function returns.
|
|
</para> </listitem>
|
|
|
|
<listitem> <para> <function> intf_WarnHexDump </function> ( <parameter>
|
|
int i_level, void * p_data, int i_size </parameter> ) :
|
|
Dumps <parameter> i_size </parameter> bytes from <parameter>
|
|
p_data </parameter> in hexadecimal. <parameter> i_level </parameter>
|
|
works like <function> intf_WarnMsg </function>. This is useful for
|
|
debugging purposes. </para> </listitem>
|
|
|
|
<listitem> <para> <function> intf_FlushMsg </function> () :
|
|
Flush the message queue, if it is in use. </para> </listitem>
|
|
</itemizedlist>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> Command line options </title>
|
|
|
|
<para>
|
|
VLC uses GNU getopt to parse command line options. getopt structures are
|
|
defined in <filename> src/interface/main.c </filename> in the "Command
|
|
line options constants" section. To add a new option This section needs
|
|
to be changed, along with
|
|
<function> GetConfiguration </function> and <function> Usage</function>.
|
|
</para>
|
|
|
|
<para>
|
|
Most configuration directives are exchanged via the environment array,
|
|
using <function> main_Put*Variable </function> and <function>
|
|
main_Get*Variable</function>. As a result, <command>
|
|
./vlc --height 240 </command> is strictly equivalent to : <command>
|
|
vlc_height=240 ./vlc</command>. That way configuration variables are
|
|
available everywhere, including plugins.
|
|
</para>
|
|
|
|
<warning> <para>
|
|
Please note that for thread-safety issues, you should not use
|
|
<function> main_Put*Variable </function> once the second thread has
|
|
been spawned.
|
|
</para> </warning>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> Playlist management </title>
|
|
|
|
<para>
|
|
The playlist is created on startup from files given in the command line.
|
|
An appropriate interface plugin can then add or remove files from it.
|
|
Functions to be used are described in <filename>
|
|
src/interface/intf_playlist.c</filename>.
|
|
<function> intf_PlaylistAdd </function> and <function>
|
|
intf_PlaylistDelete</function> are typically the most common used.
|
|
</para>
|
|
|
|
<para>
|
|
The main interface loop <function> intf_Manage </function> is then
|
|
supposed to <emphasis> start and kill input threads </emphasis> when necessary.
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> Module bank </title>
|
|
|
|
<para>
|
|
On startup, VLC creates a bank of all available .so files (plugins) in
|
|
<filename>., ./lib, /usr/local/lib/videolan/vlc</filename> <constant>
|
|
(PLUGIN_PATH)</constant>, and built-in plugins. Every plugin is checked
|
|
with its capabilities, which are :
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem> <para> MODULE_CAPABILITY_INTF : An interface plugin ;
|
|
</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_ACCESS : A sam-ism, unused at
|
|
present ;</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_INPUT : An input plugin, for
|
|
instance PS or DVD ;</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_DECAPS : A sam-ism, unused at
|
|
present ;</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_ADEC : An audio decoder ;
|
|
</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_VDEC : A video decoder ;
|
|
</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_MOTION : A motion compensation
|
|
module (for the video decoder) ;</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_IDCT : An IDCT module (for
|
|
the video decoder) ;</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_AOUT : An audio output module ;
|
|
</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_VOUT : A video output module ;
|
|
</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_YUV : A YUV module (for the
|
|
video output) ;</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_AFX : An audio effects plugin
|
|
(for the audio output ; unimplemented) ;</para> </listitem>
|
|
<listitem> <para> MODULE_CAPABILITY_VFX : A video effects plugin
|
|
(for the video output ; unimplemented) ;</para> </listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
How to write a plugin is described in the latter sections. Other threads
|
|
can request a plugin descriptor with <function> module_Need </function>
|
|
<parameter> ( module_bank_t * p_bank, int i_capabilities, void * p_data ).
|
|
p_data </parameter> is an optional parameter (reserved for future use) for the
|
|
<function> pf_probe() </function> function. The returned module_t
|
|
structure contains pointers to the functions of the plug-in. See
|
|
<filename>include/modules.h</filename> for more information.
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> The interface main loop </title>
|
|
|
|
<para>
|
|
The interface thread will first look for a suitable interface plugin.
|
|
Then it enters the main interface loop, with the plugin's <function>
|
|
pf_run </function> function. This function will do what's appropriate,
|
|
and every 100 ms will call (typically via a GUI timer callback)
|
|
<function>intf_Manage</function>.
|
|
</para>
|
|
|
|
<para>
|
|
<function>intf_Manage</function> cleans up the module bank by unloading
|
|
unnecessary modules, manages the playlist, and flushes waiting
|
|
messages (if the message queue is in use).
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1> <title> How to write an interface plugin </title>
|
|
|
|
<sect2> <title> API for the Module </title>
|
|
<para>
|
|
Have a look the files in directories
|
|
<filename>modules/misc/control</filename>,
|
|
<filename> modules/misc/dummy</filename>,
|
|
<filename> modules/misc/access</filename>,
|
|
or <filename> modules/gui</filename>. However the GUI interfaces are
|
|
not very easy to understand, since they are quite big. I suggest to
|
|
start digging into a non-graphical interface modules first. For example
|
|
<filename>modules/control/hotkeys.c</filename>.</para>
|
|
|
|
<para>An interface module is made of 3 entry functions and a module
|
|
description:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
|
|
<listitem> <para> The module description is made of macros that
|
|
declares the capabilities of the module (interface, in this case)
|
|
with their priority, the module description as it will appear in
|
|
the preferences of GUI modules that implement them, some
|
|
configuration variables specific to the module, shortcuts,
|
|
sub-modules, etc. </para></listitem>
|
|
|
|
<listitem> <para> <function> Open </function> ( <parameter>
|
|
vlc_object_t* p_object </parameter> ): This is called by
|
|
VLC to initialize the module. </para></listitem>
|
|
|
|
<listitem> <para> <function> Run </function> ( <parameter>
|
|
vlc_object_t* p_object </parameter> ): really does the job
|
|
of the interface module (waiting for user input and
|
|
displaying info). It should check periodically that
|
|
<constant>p_intf->b_die</constant> is
|
|
not <constant>VLC_TRUE</constant>.
|
|
</para></listitem>
|
|
|
|
<listitem> <para> <function> Close ( <parameter> vcl_object_t *
|
|
p_object </parameter> ) </function> function is called by VLC to
|
|
uninitialize the module (basically, this consists in destroying
|
|
whatever have been allocated
|
|
by <function>Open</function>) </para></listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
<para>The above functions take a <parameter>vlc_object_t*</parameter>
|
|
as argument, but that may need to be cast into
|
|
a <parameter>intf_thread_t*</parameter> depending on your needs. This
|
|
structure is often needed as a parameter for exported VLC functions,
|
|
such as <function>msg_Err()</function>, <function>msg_Warn()</function>,
|
|
...</para>
|
|
|
|
<para>
|
|
Define <parameter>intf_sys_t</parameter> to contain any variable you
|
|
need (don't use static variables, they suck in a multi-threaded
|
|
application :-).</para>
|
|
|
|
<para>If additional capabilities (such as Open button,
|
|
playlist, menus, etc.) are needed, consult one of the GUI modules.
|
|
One of the simpler GUI modules to consult might be
|
|
<filename>modules/gui/ncurses/ncurses.c</filename>. It is a quite
|
|
simple complete interface module with playlist interaction, and
|
|
progress bar, among other things.
|
|
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2><title>Arranging for your Module to get Compiled</title>
|
|
|
|
<para>If you create a new directory for your module, add
|
|
a <filename>Modules.am</filename> file in it. In this file, put
|
|
something like : <constant>SOURCES_yourmodule = myfile1.c
|
|
myfile2.c</constant></para>
|
|
|
|
<para>Then go to the main <filename>configure.ac</filename> file, and
|
|
add in the <constant>AC_CONFIG_FILES</constant> section (towards the
|
|
end of the file) a line similar to the others.</para>
|
|
|
|
<para>If you don't create a directory for your plugin (but instead
|
|
just put it in an existing directory), you only have to add the two
|
|
SOURCES_... lines to the existing <filename>Modules.am</filename>
|
|
file</para>
|
|
|
|
<para>This declares your module; it does not arrange for it to be
|
|
automatically compiled; automatic compilatoin is described further
|
|
below.</para>
|
|
|
|
<para>You do not write a <filename>Makefile</filename> for your
|
|
module. Instead this is done via the bootstrap and configuration
|
|
process. So now run:
|
|
</para>
|
|
|
|
<!---don't know if <xmp> or <example> works. Until then... -->
|
|
<para><filename>./bootstrap</filename></para>
|
|
<para><filename>./configure</filename> <emphasis>configure-options</emphasis></para>
|
|
<para><filename>make</filename></para>
|
|
|
|
<para>To build the module manually, go to the
|
|
directory it resides and type
|
|
<constant>make libyourmodule_plugin.so</constant> (or .dll, or
|
|
whatever the file type for a shared library is on your Operating
|
|
System.)</para>
|
|
|
|
<para>To <emphasis>automatically</emphasis> have your module get
|
|
built, you also set this in the <filename>configure.ac</filename>
|
|
file; add your module name to the <constant>default modules</constant>
|
|
section in one of the
|
|
<constant>AX_ADD_PLUGINS</constant> directives.</para>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|