Difference between revisions of "Hacker Guide/How To Write a Module"
Line 1: | Line 1: | ||
− | |||
− | |||
VLC is based on many independent modules, like most competing multimedia frameworks. Each module introduces a new functionnality. | VLC is based on many independent modules, like most competing multimedia frameworks. Each module introduces a new functionnality. | ||
This article focuses an adding a new module (a.k.a. plug-in) to VLC. You '''will need to read''' [[Documentation:Hacker%27s_Guide/Core#VLC_Pipeline_and_Modularity|VLC Core and Modules ]] and [[Documentation:VLC_Modules_Loading|How VLC loads modules]] first, otherwise you will not be able to flesh out the content of your new module. | This article focuses an adding a new module (a.k.a. plug-in) to VLC. You '''will need to read''' [[Documentation:Hacker%27s_Guide/Core#VLC_Pipeline_and_Modularity|VLC Core and Modules ]] and [[Documentation:VLC_Modules_Loading|How VLC loads modules]] first, otherwise you will not be able to flesh out the content of your new module. | ||
− | == | + | == In-tree and out-of-tree modules == |
+ | |||
+ | Most existing VLC modules are provided as source code within the main VLC source code repository (and also the source tarballs). They are compiled at the same time as the VLC core, and usually provided distributed together with VLC binary packages and installers. These modules are called in-tree modules. | ||
+ | |||
+ | However, it is also possible to write and compile VLC modules outside of VLC. That some pros and cons over developping modules in-tree: | ||
+ | ===Pros=== | ||
+ | * Compilation is a lot faster (VLC and other modules are not included in the process). | ||
+ | * You can use your own version control system, or even none at all. | ||
+ | * The copyright license does not need to abide by the requirements of the [[VideoLAN]] association for inclusion in VLC. | ||
+ | * The source code does not need to be provided, reviewed and accepted by the VLC developers. | ||
+ | * The release schedule is independent of VLC releases. New versions of the module can be published at any time regardless of VLC release planning. | ||
+ | * Different programming languages can be used at least in theory. (The main VLC code base only uses C, C++ and Lua, and on MacOS Objective C.) | ||
+ | * The module can use software libraries that would be inadequate for VLC to depend on. | ||
+ | |||
+ | ===Cons=== | ||
+ | * The VLC developers will not be review the code, which would be a good opportunity fo improve the code quality. | ||
+ | * VLC translators will not take care of localization for the module(s) where applicable. VLC is translated in many tens of languages. | ||
+ | * The module(s) cannot be distributed through the [http://www.videolan.org/ videolan.org] website and use the VideoLAN infrastructure such as the bug tracker and the build bots. | ||
+ | * The module(s) will only work with the particular VLC (major) version that it has been compiled for. For instance, a module compiled for VLC 1.1.x will not work with VLC 1.0.x or VLC 2.0.x. | ||
+ | * The module(s) will only work on the particular operating systems and architecture that is has been compiled for. For instance, a Windows 32-bits module will only work with Windows 32-bits versions of VLC. VLC supports many different combinations of operating systems and architectures. | ||
+ | |||
+ | == In-tree module integration == | ||
=== Git === | === Git === | ||
Line 13: | Line 32: | ||
==== Modules.am ==== | ==== Modules.am ==== | ||
− | First, find the right | + | First, find the right subdirectory under [[Modules_source_tree| modules/]] to add your new code. |
− | # If | + | # If the module has only one source code file module, simply add it in the subdirectory (e.g. modules/control/foo.c). |
− | + | # Larger modules should get a sub-subdirectory of their own (e.g. modules/control/foo/*). | |
− | |||
− | |||
− | # | ||
− | For example, the file {{VLCSourceFile|name=modules/ | + | Then you need to declare the module in the build system. For example, the file {{VLCSourceFile|name=modules/control/Modules.am}} tells the build system which source files are needed for each control module. |
− | Note that the indentation in Modules.am uses | + | Note that the indentation in Modules.am uses tabulations (ASCII 0x09), not white spaces. |
==== configure.ac ==== | ==== configure.ac ==== | ||
− | + | If the module depends on some new library, some architecture or some operating system characteristics, you may need to extend configure.ac to detect when and how to build the module. Refer to the configure.ac file and the [http://www.gnu.org/software/autoconf/manual/index.html GNU autoconf documentation] for details. | |
− | + | Once this is done, you should only need to rebuild VLC: | |
− | . | + | make |
+ | (This will probably trigger a re-run of autoconf and automake, so it might take a while). | ||
=== Loading your module === | === Loading your module === |
Revision as of 16:35, 26 January 2012
VLC is based on many independent modules, like most competing multimedia frameworks. Each module introduces a new functionnality.
This article focuses an adding a new module (a.k.a. plug-in) to VLC. You will need to read VLC Core and Modules and How VLC loads modules first, otherwise you will not be able to flesh out the content of your new module.
Contents
In-tree and out-of-tree modules
Most existing VLC modules are provided as source code within the main VLC source code repository (and also the source tarballs). They are compiled at the same time as the VLC core, and usually provided distributed together with VLC binary packages and installers. These modules are called in-tree modules.
However, it is also possible to write and compile VLC modules outside of VLC. That some pros and cons over developping modules in-tree:
Pros
- Compilation is a lot faster (VLC and other modules are not included in the process).
- You can use your own version control system, or even none at all.
- The copyright license does not need to abide by the requirements of the VideoLAN association for inclusion in VLC.
- The source code does not need to be provided, reviewed and accepted by the VLC developers.
- The release schedule is independent of VLC releases. New versions of the module can be published at any time regardless of VLC release planning.
- Different programming languages can be used at least in theory. (The main VLC code base only uses C, C++ and Lua, and on MacOS Objective C.)
- The module can use software libraries that would be inadequate for VLC to depend on.
Cons
- The VLC developers will not be review the code, which would be a good opportunity fo improve the code quality.
- VLC translators will not take care of localization for the module(s) where applicable. VLC is translated in many tens of languages.
- The module(s) cannot be distributed through the videolan.org website and use the VideoLAN infrastructure such as the bug tracker and the build bots.
- The module(s) will only work with the particular VLC (major) version that it has been compiled for. For instance, a module compiled for VLC 1.1.x will not work with VLC 1.0.x or VLC 2.0.x.
- The module(s) will only work on the particular operating systems and architecture that is has been compiled for. For instance, a Windows 32-bits module will only work with Windows 32-bits versions of VLC. VLC supports many different combinations of operating systems and architectures.
In-tree module integration
Git
If you plan to submit your work to VLC upstream, be sure to look at the git introduction and check the send patches part.
Compiling your module
Modules.am
First, find the right subdirectory under modules/ to add your new code.
- If the module has only one source code file module, simply add it in the subdirectory (e.g. modules/control/foo.c).
- Larger modules should get a sub-subdirectory of their own (e.g. modules/control/foo/*).
Then you need to declare the module in the build system. For example, the file modules/control/Modules.am tells the build system which source files are needed for each control module.
Note that the indentation in Modules.am uses tabulations (ASCII 0x09), not white spaces.
configure.ac
If the module depends on some new library, some architecture or some operating system characteristics, you may need to extend configure.ac to detect when and how to build the module. Refer to the configure.ac file and the GNU autoconf documentation for details.
Once this is done, you should only need to rebuild VLC:
make
(This will probably trigger a re-run of autoconf and automake, so it might take a while).
Loading your module
VLC keeps the cache of its modules, you shouldn't need to clean it, but you can use vlc --reset-plugins-cache to force a reset.
Then use
vlc -vvv --color --list
to check that your plugin is seen by VLC media player.
You should also see it in the plugins dialog of the Qt interface (Linux and Windows).
Example of an empty module
We will start with a small example, so you can understand it better.
/***************************************************************************** * Preamble *****************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <vlc_common.h> #include <vlc_plugin.h> /***************************************************************************** * Local prototypes. *****************************************************************************/ static int Open ( vlc_object_t * ); static void Close ( vlc_object_t * ); /***************************************************************************** * Module descriptor *****************************************************************************/ vlc_module_begin() set_shortname( _("testmodule") ) set_description( _("testmodle plug-in") ) set_capability( "testing", 0 ) set_callbacks( Open, Close ) set_category( CAT_INTERFACE ) /* choose relevant category, default categories in vlc/include/vlc_configuration.h */ add_integer( "test-angle", 1, "DVD Angle", "Default DVD Angle", false) vlc_module_end () /***************************************************************************** * Open: initialize interface *****************************************************************************/ static int Open( vlc_object_t *p_this ) { } /***************************************************************************** * Close: destroy interface *****************************************************************************/ static void Close( vlc_object_t *p_this ) { }
How to write the module, aka Explanations about the empty module
Module Descriptor
A VLC media player module must include a description of itself, and the parameters it accepts.
The module descriptor begins with:
vlc_module_begin();
You should set some basic information about your module:
set_shortname( _("DVD without menus") ); set_description( _("DVDRead Input") ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_ACCESS );
Note the use of _("") to create a string that needs to be translated.
Capability and score
The capability is key to the module loading.
It defines the type of module we are dealing with, whether it is an access, a demux, a decoder or else...
Now is the time to re-read how VLC loads modules.
- If VLC needs to load a specific name, it will load it by its name and VLC directly opens this module
- If VLC needs a type of modules ("I need a decoder"), VLC will load all modules matching this capability by decreasing score order until one modules's Open() function (see later) returns VLC_SUCCESS.
See the major types of capabilities of VLC.
Score should be an integer, and related to other scores in the same category. Score 0 is a special case.
Definition Example:
set_capability( "testing", 10 )
This defines a module of "testing" capability and a score of 10.
Configuration Categories and SubCategories
You should use one of the predefined categories for configuration.
The Configuration Categories and Subcategories define where the module will appear in the preferences.
The configuration categories include:
- CAT_INTERFACE
- CAT_AUDIO
- CAT_VIDEO
- CAT_INPUT
- CAT_SOUT
- CAT_ADVANCED
- CAT_PLAYLIST
You should use one of predefined sub-categories too.
See include/vlc_configuration.h for definition of all configuration categories and sub-categories.
Configuration and Parameters Options
You will need options for your module. Defining new options is easy.
All options definitions take the following argument list:
add_integer(name, value, text, longtext, advanced)
- name is the string that identifies this parameter in the configuration. This name is used at the command prompt to set the configuration value.
- value is the default value for this parameter,
- text A short description of the parameter, use _("") to create a string that needs to be translated,
- longtext A complete description of the parameter, use _("") to create a string that needs to be translated,
- advanced Boolean, ADVanced Configuration. If TRUE, this parameter will only be displayed when using the --advanced flag. e.g.
You may add the following options/parameter types to your module:
- add_integer,
- add_string,
- add_float,
- add_bool,
- add_key,
- add_file,
- add_directory,
For complete definitions, see include/vlc_plugin.h
Callback
The opening and closing static functions, detailed afterwards, need to be defined in the descriptor, so VLC can discuss with the module.
The set_callbacks() macro allows you to define 2 parameters: the first parameter is the pf_activate callback, and the second one, pf_deactivate (though the functions are most called "Open" and "Close" respectively). VLC invokes the pf_activate callback if/when it needs a plugin instance providing the correct interface, as declared with the set_capability() macro.
Open(vlc_object_t *)
The most important function of a module, is the opening: the usually-named Open() function.
static int Open ( vlc_object_t * );
The Open() function is called when the VLC core tries to open the module, and wants to load it.
During Open(), setup of structures, devices or I/O, checks should be done. A working open should return VLC_SUCCESS. In all other cases, it will not be considered as loaded.
The Open() function is expected to allocate private data (if any), and set up the private structure.
If the Opening fails, you need to clean-up your own structures.
Close(vlc_object_t *)
The second most important function of a module, is the closing: the usually-named Close() function.
static int Close ( vlc_object_t * );
The Close() function is called when the VLC core tries to close or unload an already-loaded module.
NB: If the Open() function failed, Close() will not get called.
During Close(), close devices or I/O and cleaning of structures should be done. Do not leak memory here!
The Close() function should deallocate private data.
SubModules
Submodules, created in some modules with
add_submodule()
work exactly the same way as modules. They are useful to parent modules, and to share code between modules.
The submodules will be separated in the cache, and will be loaded by VLC in the exact same way as a module.
Modules types
Depending on the module capability, you will need more information, about the necessary functions to implement.
We will detail those here:
- Access
- Demux
- Access_Demux
- Decoder
- Interface
- Video filter
- Audio filter
- Audio output
Module load troubleshooting
Sometimes, it doesn't work, because of some libtool or system bug.
You probably need to go to the root of your VLC source tree, and do something akin to the following. The examples here assume the bash shell.
Medium version (try this first)
find . -name .deps -exec rm -rf \{\} \;
./bootstrap
./configure
The dangerous-looking recursive rm -rf deletes the dependency caches in the source tree.
This ensures that the build system finds your new files. Then you can go on as usual:
./compile
And finally:
./vlc --reset-plugins-cache
Mild version
Sometimes config.status after resetting the .deps cache is enough:
find . -name .deps -exec rm -rf \{\} \;
./config.status
./compile
./vlc --reset-plugins-cache
...but not always, so it may save some headaches to always use the "medium version" above.
Extreme version
If the above didn't help, you can use this more extreme version:
find . -name .deps -exec rm -rf \{\} \;
find . -name .libs -exec rm -rf \{\} \;
./bootstrap
./configure
./compile
./vlc --reset-plugins-cache
...which also deletes library caches. Note that when you do this, you must run configure and not just config.status, because config.status runs configure in --no-create mode, which will not re-create the .libs caches.
Out of Tree Compile
If you need to compile just a module, please read out of tree compilation.
Please read the Documentation Editing Guidelines before you edit the documentation