Using Plugins

Creating complex Disko applications or to share code between several different application is a difficult task. To make it a bit easiear Disko makes use of plugins which are added dynamically at runtime. This tutorial shows how plugins work and interact.

To download the code for this tutorial, fetch it from the git-repository by issuing:

git clone git://www.diskohq.org/disko-tutorials.git

Then you can follow this part by having a look at the tutorials firststeps/06 folder.

Prerequisites

Disko stores it plugin informations within an sqlite database. This database contains the filename and location of a plugin as well as plugin specific parameters. (see firststeps/05/scripts/createdb.sql

What is a plugin?

Pluigns are basically just shared libraries that implement a specific interface. There are four types of plugins that are used for different purposes:

Backend plugins
are used to provide certain background services in applications like central audio control or data services.
Central plugins
are used for the application main functionality that is interacting with the user. These plugins normally contain funcitons that cannot be used at the same timm like A softphone and a watching TV.
OSD plugins
contain "minor" functionality that could be combined with a main application main function, e.g. a weather report that could be accessed while an application is showing TV.
Import plugins
can be used for anything that needs to be scheduled regularly. Its original purpose was to schedule data imports on a regular basis like EPG imports for a TV application. The schedules can be defined in the database as well, and are caried out by the import scheduler.

How to create a plugin?

Plugins are created by implementing one of the plugin interface classes: IMMSCentralPlugin, IMMSOSDPlugin, IMMSBackendPlugin, IMMSImportPlugin. The most simple backend plugin defintion looks as follows:

class MyBackend : public IMMSBackend {
    public:
        bool initialize(MMSPluginData data, IMMSSwitcher *switcher);
        bool onEvent(IMMSEvent event);
        bool shutdown();

        MyBackend();
        ~MyBackend();

};

There are 3 methods that are essential for the backend plugin operation:

initialize()
This method is called once by the plugin manager at the application startup or whenever the plugin is loaded for the first time. A MMSPluginData and a pointer to a switching object is passed. The MMSPluginData object contains the runtime information that is stored in the configuration database that was already mentioned. All that is needed for the plugin to function properly should be done in this method
shutdown()
This method is called by the plugin manager when the application, or when a plugin is unloaded.
onEvent()
This method is the "ear" of every plugin. It is invoked by the event manager when an event meets the plugins event subsription criteria, enabling the different plugins to communicate in a very effective way. That will be dealt with later on.

The Central and OSD Plugins have 2 additional methods that are ivoked for showing their contents. These will be discussed in a later tutorial.

Plugin loading

There is a special method that needs to be defined so that the plugin load procedure can be found by the plugin manager. For conveinience purposes we added some macros (MMS_EXPORT_BACKEND_PLUGIN, MMS_EXPORT_CENTRAL_PLUGIN, MMS_EXPORT_OSD_PLUGIN, MMS_EXPORT_IMPORT_PLUGIN) to do that. In our example this would be:

MMS_EXPORT_BACKEND_PLUGIN(MyBackend);

To enable the plugin within the disko application, some registration needs to be done in the configuration database:

INSERT OR IGNORE INTO Plugins 
       (PluginName,
        PluginTitle,
        PluginDescription,
        Filename,
        PluginPath,
        Active,
        Icon
        SelectedIcon,
        SmallIcon,
        SmallSelectedIcon,
        PluginTypeID,
        CategoryID,
        Orderpos)
VALUES ("MyBackend",
        "",
        "my first backend plugin",
        "./plugins/mybackend/libmybackendplugin.so",
        "./plugins/mybackend/",
        "Y",
        "",
        "",
        "",
        "",
        (SELECT ID FROM PluginTypes WHERE (PluginTypeName = 'BACKEND_PLUGIN')),
        (SELECT ID FROM Category WHERE (CategoryName = 'NA')),-1);

To register one ore more parameters for the plugin, some additional SQL is needed:

-- optional plugin parameters 
INSERT OR IGNORE INTO PluginProperties 
       (PluginID,
        Parameter,
        Value,
        TYPE,
        VALLIST,
        SEPARATOR)
VALUES((select ID from Plugins WHERE PluginName = 'MyBackend'),
        "message",
        "hello world!",
        "string",
        "",
        "");

This defines a parameter named message for the freshly inserted backend plugin.