SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
pluginmanager.cpp
Go to the documentation of this file.
1 // Copyright (C) 2016-2019 Edouard Griffiths, F4EXB //
3 // //
4 // This program is free software; you can redistribute it and/or modify //
5 // it under the terms of the GNU General Public License as published by //
6 // the Free Software Foundation as version 3 of the License, or //
7 // (at your option) any later version. //
8 // //
9 // This program is distributed in the hope that it will be useful, //
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
12 // GNU General Public License V3 for more details. //
13 // //
14 // You should have received a copy of the GNU General Public License //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
17 
18 #include <QCoreApplication>
19 #include <QPluginLoader>
20 #include <QDebug>
21 
22 #include <cstdio>
23 
26 #include "settings/preset.h"
27 #include "util/message.h"
30 
31 #include "plugin/pluginmanager.h"
32 
33 const QString PluginManager::m_localInputHardwareID = "LocalInput";
34 const QString PluginManager::m_localInputDeviceTypeID = "sdrangel.samplesource.localinput";
35 const QString PluginManager::m_remoteInputHardwareID = "RemoteInput";
36 const QString PluginManager::m_remoteInputDeviceTypeID = "sdrangel.samplesource.remoteinput";
37 const QString PluginManager::m_fileInputHardwareID = "FileInput";
38 const QString PluginManager::m_fileInputDeviceTypeID = "sdrangel.samplesource.fileinput";
39 
40 const QString PluginManager::m_localOutputHardwareID = "LocalOutput";
41 const QString PluginManager::m_localOutputDeviceTypeID = "sdrangel.samplesource.localoutput";
42 const QString PluginManager::m_remoteOutputHardwareID = "RemoteOutput";
43 const QString PluginManager::m_remoteOutputDeviceTypeID = "sdrangel.samplesink.remoteoutput";
44 const QString PluginManager::m_fileSinkHardwareID = "FileSink";
45 const QString PluginManager::m_fileSinkDeviceTypeID = "sdrangel.samplesink.filesink";
46 
47 const QString PluginManager::m_testMIMOHardwareID = "TestMI";
48 const QString PluginManager::m_testMIMODeviceTypeID = "sdrangel.samplemimo.testmi";
49 
50 PluginManager::PluginManager(QObject* parent) :
51  QObject(parent),
52  m_pluginAPI(this)
53 {
54 }
55 
57 {
58  // freeAll();
59 }
60 
61 void PluginManager::loadPlugins(const QString& pluginsSubDir)
62 {
63  loadPluginsPart(pluginsSubDir);
65 }
66 
67 void PluginManager::loadPluginsPart(const QString& pluginsSubDir)
68 {
69  QString applicationDirPath = QCoreApplication::instance()->applicationDirPath();
70  QStringList PluginsPath;
71 
72  // NOTE: not the best solution but for now this is
73  // on make install [PREFIX]/bin and [PREFIX]/lib/sdrangel
74  PluginsPath << applicationDirPath + "/../lib/sdrangel/" + pluginsSubDir;
75  // on build
76  PluginsPath << applicationDirPath + "/lib/" + pluginsSubDir;
77 #ifdef __APPLE__
78  // on SDRAngel.app
79  PluginsPath << applicationDirPath + "/../Resources/lib/" + pluginsSubDir;
80 #elif defined(_WIN32) || defined(WIN32)
81  PluginsPath << applicationDirPath + "/" + pluginsSubDir;
82 #endif
83 
84  // NOTE: exit on the first folder found
85  bool found = false;
86  foreach (QString dir, PluginsPath)
87  {
88  QDir d(dir);
89  if (d.entryList(QDir::Files).count() == 0) {
90  qDebug("PluginManager::loadPluginsPart folder %s is empty", qPrintable(dir));
91  continue;
92  }
93 
94  found = true;
95  loadPluginsDir(d);
96  break;
97  }
98 
99  if (!found)
100  {
101  qCritical("No plugins found. Exit immediately.");
102  exit(EXIT_FAILURE);
103  }
104 }
105 
107 {
108  qSort(m_plugins);
109 
110  for (Plugins::const_iterator it = m_plugins.begin(); it != m_plugins.end(); ++it)
111  {
112  it->pluginInterface->initPlugin(&m_pluginAPI);
113  }
114 
118 }
119 
120 void PluginManager::registerRxChannel(const QString& channelIdURI, const QString& channelId, PluginInterface* plugin)
121 {
122  qDebug() << "PluginManager::registerRxChannel "
123  << plugin->getPluginDescriptor().displayedName.toStdString().c_str()
124  << " with channel name " << channelIdURI;
125 
126  m_rxChannelRegistrations.append(PluginAPI::ChannelRegistration(channelIdURI, channelId, plugin));
127 }
128 
129 void PluginManager::registerTxChannel(const QString& channelIdURI, const QString& channelId, PluginInterface* plugin)
130 {
131  qDebug() << "PluginManager::registerTxChannel "
132  << plugin->getPluginDescriptor().displayedName.toStdString().c_str()
133  << " with channel name " << channelIdURI;
134 
135  m_txChannelRegistrations.append(PluginAPI::ChannelRegistration(channelIdURI, channelId, plugin));
136 }
137 
138 void PluginManager::registerSampleSource(const QString& sourceName, PluginInterface* plugin)
139 {
140  qDebug() << "PluginManager::registerSampleSource "
141  << plugin->getPluginDescriptor().displayedName.toStdString().c_str()
142  << " with source name " << sourceName.toStdString().c_str();
143 
145 }
146 
147 void PluginManager::registerSampleSink(const QString& sinkName, PluginInterface* plugin)
148 {
149  qDebug() << "PluginManager::registerSampleSink "
150  << plugin->getPluginDescriptor().displayedName.toStdString().c_str()
151  << " with sink name " << sinkName.toStdString().c_str();
152 
154 }
155 
156 void PluginManager::registerSampleMIMO(const QString& mimoName, PluginInterface* plugin)
157 {
158  qDebug() << "PluginManager::registerSampleMIMO "
159  << plugin->getPluginDescriptor().displayedName.toStdString().c_str()
160  << " with MIMO name " << mimoName.toStdString().c_str();
161 
163 }
164 
165 void PluginManager::loadPluginsDir(const QDir& dir)
166 {
167  QDir pluginsDir(dir);
168 
169  foreach (QString fileName, pluginsDir.entryList(QDir::Files))
170  {
171  if (QLibrary::isLibrary(fileName))
172  {
173  qDebug("PluginManager::loadPluginsDir: fileName: %s", qPrintable(fileName));
174 
175  QPluginLoader* pluginLoader = new QPluginLoader(pluginsDir.absoluteFilePath(fileName));
176  if (!pluginLoader->load())
177  {
178  qWarning("PluginManager::loadPluginsDir: %s", qPrintable(pluginLoader->errorString()));
179  delete pluginLoader;
180  continue;
181  }
182 
183  PluginInterface* instance = qobject_cast<PluginInterface*>(pluginLoader->instance());
184  if (instance == nullptr)
185  {
186  qWarning("PluginManager::loadPluginsDir: Unable to get main instance of plugin: %s", qPrintable(fileName) );
187  delete pluginLoader;
188  continue;
189  }
190 
191  delete(pluginLoader);
192 
193  qInfo("PluginManager::loadPluginsDir: loaded plugin %s", qPrintable(fileName));
194  m_plugins.append(Plugin(fileName, instance));
195  }
196  }
197 }
198 
199 void PluginManager::listTxChannels(QList<QString>& list)
200 {
201  list.clear();
202 
203  for(PluginAPI::ChannelRegistrations::iterator it = m_txChannelRegistrations.begin(); it != m_txChannelRegistrations.end(); ++it)
204  {
205  const PluginDescriptor& pluginDescipror = it->m_plugin->getPluginDescriptor();
206  list.append(pluginDescipror.displayedName);
207  }
208 }
209 
210 void PluginManager::listRxChannels(QList<QString>& list)
211 {
212  list.clear();
213 
214  for(PluginAPI::ChannelRegistrations::iterator it = m_rxChannelRegistrations.begin(); it != m_rxChannelRegistrations.end(); ++it)
215  {
216  const PluginDescriptor& pluginDesciptor = it->m_plugin->getPluginDescriptor();
217  list.append(pluginDesciptor.displayedName);
218  }
219 }
220 
221 void PluginManager::createRxChannelInstance(int channelPluginIndex, DeviceUISet *deviceUISet, DeviceAPI *deviceAPI)
222 {
223  if (channelPluginIndex < m_rxChannelRegistrations.size())
224  {
225  PluginInterface *pluginInterface = m_rxChannelRegistrations[channelPluginIndex].m_plugin;
226  BasebandSampleSink *rxChannel = pluginInterface->createRxChannelBS(deviceAPI);
227  pluginInterface->createRxChannelGUI(deviceUISet, rxChannel);
228  }
229 }
230 
231 void PluginManager::createTxChannelInstance(int channelPluginIndex, DeviceUISet *deviceUISet, DeviceAPI *deviceAPI)
232 {
233  if (channelPluginIndex < m_txChannelRegistrations.size())
234  {
235  PluginInterface *pluginInterface = m_txChannelRegistrations[channelPluginIndex].m_plugin;
236  BasebandSampleSource *txChannel = pluginInterface->createTxChannelBS(deviceAPI);
237  pluginInterface->createTxChannelGUI(deviceUISet, txChannel);
238  }
239 }
void listRxChannels(QList< QString > &list)
static const QString m_remoteInputHardwareID
Remote input hardware ID.
const QString displayedName
static const QString m_fileSinkHardwareID
FileSink sink hardware ID.
void enumerateTxDevices(PluginManager *pluginManager)
virtual BasebandSampleSink * createRxChannelBS(DeviceAPI *deviceAPI)
void loadPlugins(const QString &pluginsSubDir)
static const QString m_testMIMODeviceTypeID
Test MIMO plugin ID.
static const QString m_localOutputDeviceTypeID
Local output plugin ID.
PluginAPI::ChannelRegistrations m_rxChannelRegistrations
Channel plugins register here.
virtual const PluginDescriptor & getPluginDescriptor() const =0
static const QString m_remoteOutputDeviceTypeID
Remote output plugin ID.
static const QString m_localOutputHardwareID
Local output hardware ID.
void registerSampleSource(const QString &sourceName, PluginInterface *plugin)
static const QString m_fileSinkDeviceTypeID
FileSink sink plugin ID.
void registerSampleSink(const QString &sinkName, PluginInterface *plugin)
void registerRxChannel(const QString &channelIdURI, const QString &channelId, PluginInterface *plugin)
PluginAPI::SamplingDeviceRegistrations m_sampleMIMORegistrations
MIMO sink plugins (one per device kind) register here.
static const QString m_localInputHardwareID
Local input hardware ID.
void enumerateMIMODevices(PluginManager *pluginManager)
void loadPluginsDir(const QDir &dir)
static const QString m_testMIMOHardwareID
Test MIMO hardware ID.
void createRxChannelInstance(int channelPluginIndex, DeviceUISet *deviceUISet, DeviceAPI *deviceAPI)
static const QString m_fileInputHardwareID
File input hardware ID.
PluginAPI::SamplingDeviceRegistrations m_sampleSinkRegistrations
Output sink plugins (one per device kind) register here.
void enumerateRxDevices(PluginManager *pluginManager)
virtual PluginInstanceGUI * createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *txChannel)
void loadPluginsPart(const QString &pluginsSubDir)
static const QString m_remoteInputDeviceTypeID
Remote input plugin ID.
void loadPluginsFinal()
static const QString m_remoteOutputHardwareID
Remote output hardware ID.
static const QString m_localInputDeviceTypeID
Local input plugin ID.
< This is the device registration
Definition: pluginapi.h:20
void registerTxChannel(const QString &channelIdURI, const QString &channelId, PluginInterface *plugin)
void listTxChannels(QList< QString > &list)
void createTxChannelInstance(int channelPluginIndex, DeviceUISet *deviceUISet, DeviceAPI *deviceAPI)
virtual PluginInstanceGUI * createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
void registerSampleMIMO(const QString &mimoName, PluginInterface *plugin)
static const QString m_fileInputDeviceTypeID
File input plugin ID.
PluginAPI::ChannelRegistrations m_txChannelRegistrations
Channel plugins register here.
PluginAPI m_pluginAPI
PluginManager(QObject *parent=0)
Plugins m_plugins
virtual BasebandSampleSource * createTxChannelBS(DeviceAPI *deviceAPI)
static DeviceEnumerator * instance()
PluginAPI::SamplingDeviceRegistrations m_sampleSourceRegistrations
Input source plugins (one per device kind) register here.