Essential Plugin Files
A plugin needs to derive its plugin definition from the "TBVPluginInterface" class. The "TBVPluginInterface.h" file must, thus, be added to any TBV plugin project containing your custom .cpp file(s). Since it is intended to not change the currently provided access functions but only to add new functions, updating the "TBVPluginInterface.h" include files does not require changing any of the files containing your own code, i.e. it will be possible to overwrite the file with a new version and to recompile the plugin code. Updating the "TBVPluginInterface.h" file will only be necessary if you want to use additional functionality of Turbo-BrainVoyager made eventually available with new releases. The latest "TBVPluginInterface.h" include file is provided with the source code of the example plugins (and eventually via download from our web site). The snapshot below shows part of the "TBVPluginInterface.h" file defining the abstract plugin class with essential virtual methods that need to be implemented in the derived plugin class.
Following the class definition, the "TBVPluginInterface.h" file contains definition of access functions with parameter types that can be used in the plugin class. The snapshot below shows the beginning of the TBV API. The "tLogText" command, for example is defined with a "void" return type and one input parameter that is a pointer to a c string. In the plugin code it will be possible to write commands like "tLogText("Hello from Plugin")" and the provided text will be visible to the user in the Log text field of the Plugin dialog. The available commands will be described in more detail in subsequent topics.Following the definition of the signature of the TBV API functions, a "InitTBVAccess()" function (not shown) is defined that retrieves the corresponding function pointers from TBV at run time.
Besides the "TBVPluginInterface.h" file, a new plugin needs as a minimum only one C++ and one header file defining the custom plugin class, e.g. a "MyPlugin.cpp" file and a "MyPlugin.h" file. The provided plugin examples contain an additional "global.h" header file that is only used to determine the platform on which the plugin is compiled in order to include platform-specific standard C/C++ header files. Depending on the needs of your plugin, you may, of course, additional C/C++ files that support your programming goals, e.g. files from "Boost" or "Numerical Recipes". The snapshot below shows the complete "SaveVolumeDataPlugin.h" header file from the "Export Volume Data" example plugin.
As described, the custom class includes the "TBVPluginInterface.h" header file allowing to derive the custom class "SaveVolumeDataPlugin" from the abstract "TBVPluginInterface" class. Within the class declaration, all methods that were defined "virtual" in the abstract class are now non-virtual and need to be defined in the implementation file "SaveVolumeData.cpp". Note that for a new plugin, one only needs to change the class name. The only special part in this example are the definitions of two protected variables "stepCounter" and "ExportChoice" that are used in the plugin to store information across different calls from TBV. You would remove these variables for your own plugin and add other variables as needed. The second part of the plugin header file contains declarations of the described C functions that need to be defined in the implementation plugin file; these functions will be called from TBV to retrieve basic information about the plugin. Note that this part needs not to be changed. The snapshot below shows part of the "SaveVolumeData.cpp" plugin class implementation file.
The constructor and destructor are empty in this example plugin. In case you allocate data on the heap in the constructor (or "initPlugin()" function), you should release that memory in the destructor. The "initPlugin()" function is used to establish access to the TBV API calling the "InitTBVAccess()" function that is defined in the "TBVPluginInterface.h" header file. It is important to check that this function succeeds; if it does not succeed calling any TBV API command will result in a crash since the function pointers could not be retrieved; as can be seen above, the "initPlugin()" function returns in that case with a value "false" indicating to TBV that the plugin can not be used. If successful, the "initPlugin()" function finally checks whether the version of the running TBV program is sufficiently high to support the subsequently used API functions. Since at this point the access to the TBV API was successful, this part can use the TBV API functions "tGetVeersionOfTBV()" and "tMessageBox()". The "checkVersionGreaterEqualVersion()" function is always available since it is defined in the "TBVPluginInterface.h" file. While you can put any code you want in the "initPlugin()" definition, it is recommended to simply use the function as described for your own code (eventually modifying the required TBV version). Note that the class name needs to be changed for all class methods, e.g. instead of "bool SaveVolumeDataPlugin::initPlugin()" you would use something like "MyPlugin::initPlugin()". The snapshot below shows the next section of the "SaveVolumeData.cpp" file.
The "executePreRun()" function can be used to prepare real-time processing or to ask the user to provide relevant information. This function is called once from TBV after the call to the "initPlugin()" function. In the example plugin, the user is asked to make a choice about the type of data to export to disk at each step during subsequent real-time processing. The choice is presented using a dialog that is invoked using the "tGetIntegerInput()" API function. Note that it is not allowed to use such blocking GUI API functions during real-time processing, i.e. in the code of the "executePreStep()" and "executePostStep()" functions since this would interfere with real-time processing. The "executePreStep()" function is not used in the example plugin simply returning "true" to TBV; since the data of a new volume is not preprocessed at this stage, this function can be used to perform custom preprocessing replacing TBV's standard preprocessing, e.g. by implementing an own motion correction routine after turning off motion correction in the TBV Settings dialog. The most important function of a plugin is the "executePostStep()" function that is called at each step during real-time processing just after all TBV analysis steps have been performed. In the example, the function begins with increasing the instance variable "stepCounter" that was declared in the header file (see above). Then some relevant information is retrieved such as the name of the project (used to name exported files) and the target folder specified in the TBV settings file; the user is informed that the exported data from this plugin is stored in that folder using the "tLogText()" API function. The value of the currently analyzed time step is retrieved by the "tGetCurrentTimePoint()" API function. Inspect the full definition of the "executePostStep()" function in the provided example plugins to learn about the offered possibilities. The snapshot below shows the final part of the "Export Volume Data" example plugin code defining the C functions declared in the header file.
As can be seen, the "createPlugin()" function creates a plugin object by instantiating the plugin class using the "new" operator. The obtained pointer to the plugin object is returned and used by TBV to call the class functions that have been described above. The "getPluginName()" C function returns a string containing the name of the plugin; TBV uses that string to represent the plugin in the Plugins menu. The "getPluginDescription()" C function provides a descriptive string summarizing the purpose of the plugin. The "getAuthor()" function returns information about the author of the plugin. The "getHelpFile()" function may return a link to a HTML file containing additional help information about using the plugin; here an empty C string is returned, i.e. no help file is provided; since TBV plugins are usually used internally (as opposed to BVQX plugins), a help file targeted to other users is probably not necessary in most cases. The final C function returns a version string (currently not used, but it might be helpful for the plugin developer to identify major revisions of a plugin).
It should be possible to write a plugin with your favorite compiler and Integrated Development Environment (IDE). On Windows, the Microsoft Visual C++ compilers in Visual Studio 2008/2010/2012 compilers have been tested and can be used to create plugins. On Mac OS X, you can use XCode or QtCreator and on Linux you can use QtCreator or KDevelop. On Mac and Linux, the provided Brain Innovation plugins have been compiled directly from the console using the GNU gcc compiler or with Qt Creator. While Qt Creator is a cross-platform IDE from Digia (that got it from Nokia that acquired Trolltech, the original creator of the Qt library) to develop C++ software using the Qt library, it can be used also to develop any (non-GUI) C/C++ program/library. Project files (Visual Studio project ".vcproj" file for Windows, Makefiles for Mac and Linux) are provided that can be adapted for use with own plugins.
Copyright © 2014 Rainer Goebel. All rights reserved.