wiki:libroar/plugins

Introduction

libroar contains a plugin loader API. It can be used by any application to load plugins. It is not specific to audio or any of the RoarAudio software packages. It is designed universally and handles tasks common to all plugin interfaces such as loading of needed files, handling meta data (such as plugin name, author and description) as well as passing data between the plugin and the host application.

The plugin loader is build on top of the dynamic loader abstraction and can be used at different levels of abstraction.

Main layers

The plugin API consists of 3 main layers: the Dynamic Loader, the Plugin Loader and the Plugin Container.

The Dynamic Loader

The Dynamic Loader is a abstraction of the system's dynamic loader. It is abled to load all shared libraries and shared library formats as used by the system. It is designed similar to the POSIX dlopen() and friends.

The Plugin Loader

The Plugin Loader is build directly into the Dynamic Loader and can be activated by a single boolean setting (ra_init). If enabled it will try to find a plugin entry symbol and start loading the plugin. This includes setting up an new context for the plugin with global data and error states as well as registering all the services the plugin provides. This also checks if the plugin is actually be written for the host application so it can not crash later because of mismatching ABIs.

The Plugin Container

The Plugin Container is a separate module. It can store multiple plugins at the same time and makes it easy for an application to handle them. A application using the container does not need to keep a list of plugins or send events to them individually but just pass the stuff to the container.

Common Services

The plugin API provides some common services as found in a lot application specific plugin interfaces.

AppSched?

The AppSched? is a way to allow the plugin to run event independed code. For example if the plugin copies data from one to another location AppSched? is used to do that job. It is normally used to implement a main loop like structure.

AppSched? works by registering callbacks for special events. The following events are defined:

Event Min. Version Description
INIT old This is called when the application wants to start the plugin. Normally you run code to open IO or build data structures here.
FREE old This is called when the plugin is no longer used (on unload). You normally close all your IO and free memory you allocated here.
UPDATE old This is called when you should do a main loop iteration. You can check your IO here and do your work. This function must not block. This is normally called once per main loop cycle of the host application.
TICK old This is a an asynchronous event. Some applications use it when doing some longer work. It can be used to sync your IO like answer re-draw requests from the X server. You must not block in this function.
WAIT old This is to ask the plugin to block and wait for new work to be done. This is normally used to wait for new IO events such as data from clients or X11 events. This can block for a long time. UPDATE is called soon after this returned so you do not need to call it from here.
ABOUT 1.0beta9-pr0 This event is used to show an about dialog. If not provided by the plugin this is automatically provided by the plugin API. Note: No callback can be set for this before libroar3.
HELP 1.0beta9-pr0 This event is used to show a help dialog. If not provided by the plugin this is automatically provided by the plugin API. Note: No callback can be set for this before libroar3.
PREFERENCES 1.0beta9-pr0 This event is used to show an options dialog. This is currently not supported.

Every AppSched? using application (every should in fact!) will send INIT, FREE and UPDATE. The usage of TICK and WAIT is optional by the application.

Context separation

The Plugin API supports context separation. This means that the plugin runs in it's own context and will not see the context of the host application or of other plugins. This also allows the same plugin to be loaded multiple times without them interacting.

The following is currently supported context separation:

  • libroar's error state
  • system's error state
  • global data of the plugin
  • global notify core
  • stdvios (roar_stdin, roar_stdout, roar_stderr)

RegFN

RegFN is a API supporting registration of services provided by the plugin. It can be used as a portable way to register any kind of services. It works by registering objects. Normally such an object is a struct with callbacks used for this service. The object is index by an FN (Global type. e.g. Application), subtype (e.g. MyUserDefinedSubtype?) and version (e.g. 0) as well as object size. The version and size is used to check if the object matches the current API/ABI as defined by the service user (e.g. the application). The application or any other interested part is now notified about registered and unregistered services using a callback. Beside service types defined by the Application there are also standard service types.

Common Protocol Interface (CPI)

The Common Protocol Interface is a service as registered by RegFN. It allows a portable implementation of any network protocol. Each protocol is implemented using a set of callback functions. In case of network events they are called by the application.

The following callbacks are defined:

Callback Name Description
set_proto Called when new client connects using this protocol
unset_proto Called when client is disconnected from this protocol
handle Called when where are new data to be handled
flush Called when output data can be send to the client
flushed Called when all output has been flushed
status Called to get client status for flow control

Common Service Interface (CSI)

The Common Service Interface is a way to register any kind of service. it is similar to RegFN but registers services (APIs) not objects. A service is defined by it's name and version as well as the name and version of the application it is used by to avoid namespace collisions. A server can for example provide support to read, write or process some kind of data. There are also some universal services defined. Those have the application name and version set to NULL. Those services are defined by the RoarAudio project and designed to do some common tasks. This is done make plugins more portable between host applications. Services can be provided and used by all parts a of program: the main program, libraries and plugins. The API as returned by the service is a plain struct with the same scope as the lhandle it is provided by (e.g. the scope of the the plugin being loaded). The struct can contain any number of functions and constant/static data. dynamic data must be passed by functions to allow context separation to work.

libroar provides some function and macros to easily build and use services.

List of Subtopics

Last modified 11 years ago Last modified on 01/15/13 15:59:12