|
Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages
HOWTO: Creating a Plugin DriverThe are two distinct type of drivers in Player:
Plugin drivers have serveral advantanges over their static counterparts:
This document describes the process for creating new plugin drivers. It assumes you are familiar with C++, class inheritance, and thread programming. A plugin driver exampleSample code for a very basic plugin driver is provided in theexamples directory; for a default install, this will be:
Copy the files from this directory and rename
This produces a plugin driver named
The driver block in the config file has an additional field
Writing a simple driverThe first step in creating a new driver is to decide which interface it will support. The existing interfaces are described in the reference section, and their various message structures and constants are defined in player.h. Although you can create a new interface, you should try to fit your driver to an existing interface, of which there are many. By deciding to support an existing interface, you'll have less work to do in the server, and will likely have instant client support for your driver in several languages.To create a new driver, you should create a new class for the driver, which should inherit from the Driver class. This base class defines a standard API, part of which the new driver must implement (other parts it may choose to override). We now describe the salient aspects of the Driver class. The constructorSimple drivers will use the following Driver constructor:
This constructor will establish the buffers and queues that allow the Player server to interface with the driver. The preamble for the example driver, for example, looks like this:
The preamble indicates that this driver:
The
This might be the serial port from which to read data, for example. See the ConfigFile documentation for the various kinds of options that can be read from the configuration file. Setup()When the first client subscribes to a driver, the driver's Setup() method is called; every driver must implement this method. The Setup() method generally does two things:
Player is a multi-threaded application, with most drivers running in their own thread; this makes it particularly easy to write drivers that read/write data from serial ports, network sockets, disk files and so on. After initialization, Setup() should return either zero to indicate that the device was successfully setup, or non-zero to indicate that setup failed (the latter will cause Player to terminate). Shutdown()When the last client unsubscribes from a device, the driver's Shutdown() method is called; every driver must implement this method. The Shutdown() method generally does two things:
Note that the ordering is important here: we must shut down the driver thread before we release the resources it is using; to this end, Driver::StopThread() will tell the driver thread to quit, and wait until it exits before returning. Shutdown() should return either zero to indicate that device was successfully shutdown, or non-zero to indicate that shutdown failed. Main()The Driver::Startup() method will result in the creation of a new thread of control, which will immediately call Driver::Main(). Every driver must this overload this method. The overloaded Main() method is generally responsible for translating between some device-specific API and the standard Player interfaces. The basic steps are as follows:
The Driver::PutData() and Driver::GetCommand() methods manage all of the buffering and locking required to synchronize the driver and server threads. The overloaded Main() method is also responsible for handling any configuration request sent to the driver; the basic steps are as follows:
Note that your driver must respond, one way or another, to each and every request. Failing to respond to requests will cause client programs to "hang" when talking to the driver.
The overloaded Main() must also be capable of graceful termination (i.e., the function should exit cleanly when the user kills the server). This can be achieved by calling InstantiationIn order to instantiate a driver, the Player server needs to know two things:
Note that this function may be called multiple times: once for each occurance of the driver name in the configuration file. Each driver must register itself with the server using the DriverTable::AddDriver(), providing the driver name and factory function. Drivers must therefore define a registration function as follows:
This function must be called exactly once, on program startup. For plugin drivers, this can be achieved by defining an initialization function for the shared object:
This function will be called when the shared object is loaded, before any drivers are instantiated. The Building the shared libraryThe example driver includes a Makefile for building shared objects. To manually build a shared object, try:
While the above method will probably work, it is recommended that you use pkg-config to get the compile flags; i.e.,
Generated on Tue May 3 14:16:08 2005 for Player by 1.3.6 |