| Developing Plug-ins for NMM | ||
|---|---|---|
| Prev | ||
The NMM registry stores information about nodes. It can be queried for nodes with certain features and it can make reservations for nodes. Every node is stored in the registry with name (e.g. "CameraNode"), type (e.g. SOURCE), its interfaces (e.g. ICamera) and its supported input and output formats stored in the property of the node.
Registering a node can be very simple. If a node does not pose any restrictions on the number of instantiations, you simply have to create a file RegisterPlugin.cpp and include that file to the library of the node. In general, nodes that do not rely on any special hardware (like a soundcard or a camera) can be instantiated as often as wanted. Or more precisely, as often as your host machine allows. The simplest RegisterPlugin.cpp will look like this.
#include "nmm/base/registry/Plugin.hpp"
#include "MyNode.hpp"
// instantiate a plugin object for each node
NMM::TPlugin< NMM::MyNode > plugin0("MyNode");
// instantiate the plugin array
NMM::Plugin* nmm_plugins[] = { &plugin0, 0 };
|
Other nodes can only be instantiated a certain number of times. For example, a node representing a TV-grabber can only be instantiated once. In these cases, you have to write code to check how many nodes can be instantiated (e.g. how many devices are available). You then have to implement a new sub class of TPlugin where the nmmRegistryInit()- and the nmmFactoryInit()-method have to be re-implemented. This step is not described here in detail. See PlaybackNode or the Plugin1394 for an example.
Is is also important to assure that a node can be initialized (by calling init()) and deinitialized (be calling deinit()) without crashing since these two methods are called by the registry. In order to find a plugin, the registry has to be able to locate the plug-in. For this, if NMM_DEV_DIR is set, then the registry will search NMM_DEV_DIR/dev-lib/ for plug-ins. If NMM_DEV_DIR is not set, the registry will search $prefix/lib for plug-ins, where $prefix is the path where NMM was installed by calling 'make install'.
If a node depends on a device (such as /dev/dsp or /dev/video0), and there may be multiple devices usable by the node (for example /dev/video0, /dev/video1, ... for a TV grabber card), then the node should be registered once for each usable device. The number of instances for each registered node must be the number of times, each device can be opened simultaneously. This is typically 1, but may be higher (for example for sound devices). The TDevicePlugin class can simplify this task. You can register your node using the following code in RegisterPlugin.cpp
#include "nmm/base/registry/DevicePlugin.hpp"
#include "MyNode.hpp"
// register one node per device found
NMM::TDevicePlugin< NMM::MyNode > plugin0("/dev/device", false, "MyNode");
// instantiate the plugin array
NMM::Plugin* nmm_plugins[] = { &plugin0, 0 };
|
This causes the plugin to check the devices /dev/device0, /dev/device1, ... and register a node for each device that can be opened. Once a device can't be opened, it stops checking for devices. For details about the constructor arguments of TDevicePlugin, see the doxygen documentation of this class.
Your node determines whether a device is useable or not. To be able to use TDevicePlugin, your node must implement the IDevice interface correctly. That is, it must be derived from IDeviceImpl, and it must provide a setDevice method which checks whether the device is useable and closes the device again. If the device can not be opened, then it must throw a DeviceNotFoundException. This exception is handled by the TDevicePlugin class. The setDevice method is only called in state CONSTRUCTED. If the device is useable, then the node must store the device name and use it in doInit to open the device. Note that usually it is enough to just check whether the device can be opened and to make sure that doInit fails if the device is not useable. Then TDevicePlugin will usually do the right thing. Otherwise you can still write a subclass of TDevicePlugin to implement extended behaviour. For an example of this, see PlaybackNode.