Difference between revisions of "AnyWave:DeveloperCorner"
(→Step 3: Let's code) |
(→Step 3: Let's code) |
||
Line 156: | Line 156: | ||
m_flags = Aw::HasExtension|Aw::CanRead; // Here we tell AnyWave that the plugin handle file extension (mostly the case) | m_flags = Aw::HasExtension|Aw::CanRead; // Here we tell AnyWave that the plugin handle file extension (mostly the case) | ||
// and we also specify CanRead flag to tell AnyWave that this is a READER plugin. | // and we also specify CanRead flag to tell AnyWave that this is a READER plugin. | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | ===Open and read the data=== | ||
+ | Now we have to implement the three methods that will allow our plugin to open and read data from a file:<br/> | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | #include "MyReader.h" | ||
+ | #include <QFile> | ||
+ | |||
+ | /// | ||
+ | /// canRead : use to open a file and check if the format is ok. | ||
+ | /// Returns a flag informing AnyWave that we can or can't read that file. | ||
+ | AwFileIO::FileStatus canRead(const QString& fileName) | ||
+ | { | ||
+ | // Here we won't really open the file, we are just going to check if we can. | ||
+ | |||
+ | // Let's suppose or .myr format is a text header file where the first line is a string with the following keyword "MYFORMAT". | ||
+ | |||
+ | QFile file(fileName); | ||
+ | if (file.open(QIODevice::ReadOnly|QIODevice::Text) // try to open as a text file. | ||
+ | { | ||
+ | QString line = file.readLine(); // read the first line. | ||
+ | if (line == "MYFORMAT") { | ||
+ | file.close(); | ||
+ | return AwFileIO::NoError; // it's OUR format! | ||
+ | } | ||
+ | } | ||
+ | return AwFileIO::WrongFormat; // We don't know this file format. | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Revision as of 15:25, 6 September 2018
Contents
Welcome
This part of the Wiki is dedicated to developers who would like to implement their own plug-ins for AnyWave.
AnyWave is written using the Qt Framework and the Qt plugin mechanism, so a good knowledge of the Qt Framework is required.
The SDK
If you have installed AnyWave on your system, you will find all the required files in the installation folder.
Linux
Build from sources following the instructions on our Gitlab.
Considering the default installation path, the requires folders to build a plugin are:
- /usr/local/AnyWave/include
- /usr/local/AnyWave/lib
Mac OS
The required folders to build a plugin are:
- /Applications/AnyWave.app/Contents/include
- /Applications/AnyWave.app/Contents/dylibs
Windows
The required folders to build a plugin are:
- AnyWave\include
- AnyWave\lib
Basic requirements to build a plugin
We strongly recommend QtCreator as the tool to use which is available along with the Qt open source package you will need to build a plugin.
Download Qt and Qt Creator here: Get Qt and Qt Creator
Note about Windows:
The Windows version of AnyWave is built with Visual Studio 2017 though, so, if you plan to build a plugin for Windows, consider using Visual Studio along with the Qt VS Addin.
Technically speaking you can build a plugin with QtCreator using another compiler like gcc or clang.
You will need to put the runtime DLL files of the chosen compiler into the AnyWave folder after you copied the plugin into the Plugins subdirectory.
Prepare a project
Every Qt project starts with a .pro file which is the format used by qmake, the tool for building Qt projects.
Building an AnyWave plugin requires that the paths to AnyWave headers and libraries must be set.
A good practice is to set an environment variable called AW_ROOT that points to the root folder of your AnyWave installation.
Example:
CONFIG += release warn_off c++11 plugin ROOT=$$(AW_ROOT) # on Mac OS the required folders are located inside the application bundle. macx{ ROOT = $$(AW_ROOT)/Contents } INCLUDEPATH += $$ROOT/include LIBS += -L$$ROOT/lib DESTDIR = $$ROOT/Plugins # Mac OS application has a separated folder for Plugins. macx { DESTDIR = $$ROOT/../../Anywave_Plugins # shared libs on Mac are located in the application bundle. LIBS += -F/Library/Frameworks -L$$ROOT/dylibs }
You may use this file as .pri that you could include in every project you plan to develop:
Get plugins.pri file
Build a reader plugin
As a tutorial, we are going to develop here a reader plugin called "My Reader".
Each Qt project starts with a .pro file which qmake use to compile and link a Qt project.
A Reader plugin is a Qt shared library that should be placed in the Plugins directory of AnyWave.
Step 1: Prepare the folder
Let's create a folder in which we will put the files required to build our plugin:
mkdir MyReader && cd MyReader
Step 2: create the project file
Now we can create the .pro file for our project:
# We assume that the plugins.pri file is also in our plugin directory. include(plugins.pri) # The name of our plugin TARGET=MyReader # Our project must be a library TEMPLATE = lib # Just to avoid unwanted libs, Qt GUI is not usefull for a reader plugin (no widgets/no graphics items). QT -= gui # We must link with some AnyWave libs # AwRW is the AnyWave ReadWrite lib. unix{ LIBS += -lAwRW } win32{ LIBS += AwReadWriteLib.lib } HEADERS += MyReader.h SOURCES += MyReader.cpp
Step 3: Let's code
The header file:
#pragma once #include <AwFileIO.h> class Q_DECL_EXPORT MyReader : public AwFileIO { Q_OBJECT Q_INTERFACES(AwFileIO) public: explicit MyReader(const QString& fileName); ~MyReader(); qint64 readDataFromChannels(float start, float duration, QList<AwChannel *>& channels) override; AwFileIO::FileStatus openFile(const QString &path) override; AwFileIO::FileStatus canRead(const QString &path) override; void cleanUpAndClose() override; }; class Q_DECL_EXPORT MyReaderPlugin : public AwFileIOPlugin { Q_OBJECT Q_INTERFACES(AwFileIOPlugin) Q_PLUGIN_METADATA(IID AwFileIOInterfacePlugin_IID) public: MyReaderPlugin(); MyReader *newInstance(const QString& fileName) { return new MyReader(fileName); } };
The header file declares two classes: One is the reader object itself and the other one is the plugin object.
The methods declared with the override keyword MUST be implemented otherwise the compiler will complain and your plugin won't be a valid AnyWave plugin.
constructor/destructor (init our plugin)
Let's have a closer look at methods we have to implement:
explicit MyReader(const QString& fileName); ~MyReader();
The constructor/destructor methods. This is where you initialise the member variables and handle the destruction by releasing allocated memory and open files.
Let's see the code for our constructor:
#include "MyReader.h" // constructor for reader object MyReader::MyReader(const QString& fileName) : AwFileIO(fileName) { // do some inits here. } // constructor of Plugin object // Here we will define the name of our Plugin and it's properties/flags for AnyWave MyReaderPlugin::MyReaderPlugin() : AwFileIOPlugin() { // define the name (must be unique in AnyWave) name = QString("MyReader Plugin"); // short description of what the plugin does. description = QString("Read My Format"); // info about manufacturer/author manufacturer = QString("Myself"); // version string version = QString("1.0"); // the file extensions the reader can open. fileExtensions = { ".myr" }; // Flags to define the behavior in AnyWave m_flags = Aw::HasExtension|Aw::CanRead; // Here we tell AnyWave that the plugin handle file extension (mostly the case) // and we also specify CanRead flag to tell AnyWave that this is a READER plugin. }
Open and read the data
Now we have to implement the three methods that will allow our plugin to open and read data from a file:
#include "MyReader.h" #include <QFile> /// /// canRead : use to open a file and check if the format is ok. /// Returns a flag informing AnyWave that we can or can't read that file. AwFileIO::FileStatus canRead(const QString& fileName) { // Here we won't really open the file, we are just going to check if we can. // Let's suppose or .myr format is a text header file where the first line is a string with the following keyword "MYFORMAT". QFile file(fileName); if (file.open(QIODevice::ReadOnly|QIODevice::Text) // try to open as a text file. { QString line = file.readLine(); // read the first line. if (line == "MYFORMAT") { file.close(); return AwFileIO::NoError; // it's OUR format! } } return AwFileIO::WrongFormat; // We don't know this file format. }