MythTV  master
mythplugin.cpp
Go to the documentation of this file.
1 // C includes
2 #ifndef _WIN32
3 #include <dlfcn.h>
4 #else
5 #include "compat.h"
6 #endif
7 
8 // Qt includes
9 #include <QDir>
10 
11 // MythTV includes
12 
13 // libmythbase
14 #include "mythplugin.h"
15 #include "mythcorecontext.h"
16 #include "mythtranslation.h"
17 #include "mythdirs.h"
18 #include "mythversion.h"
19 #include "mythlogging.h"
20 
21 int MythPlugin::init(const char *libversion)
22 {
23  using PluginInitFunc = int (*)(const char *);
24  auto ifunc = (PluginInitFunc)QLibrary::resolve("mythplugin_init");
25  if (ifunc)
26  return ifunc(libversion);
27 
28  QString error_msg(dlerror());
29  if (error_msg.isEmpty())
30  {
31  QByteArray libname = QLibrary::fileName().toLatin1();
32  (void)dlopen(libname.constData(), RTLD_LAZY);
33  error_msg = dlerror();
34  }
35 
36  LOG(VB_GENERAL, LOG_EMERG, QString("MythPlugin::init() dlerror: %1")
37  .arg(error_msg));
38 
39  return -1;
40 }
41 
42 int MythPlugin::run(void)
43 {
44  using PluginRunFunc = int (*)();
45 
46  int rVal = -1;
47  auto rfunc = (PluginRunFunc)QLibrary::resolve("mythplugin_run");
48 
49  if (rfunc)
50  rVal = rfunc();
51 
52  return rVal;
53 }
54 
56 {
57  using PluginConfigFunc = int (*)();
58 
59  int rVal = -1;
60  auto rfunc = (PluginConfigFunc)QLibrary::resolve("mythplugin_config");
61 
62  if (rfunc)
63  {
64  rVal = rfunc();
66  }
67 
68  return rVal;
69 }
70 
72 {
73  using PluginTypeFunc = MythPluginType (*)();
74  auto rfunc = (PluginTypeFunc)QLibrary::resolve("mythplugin_type");
75 
76  if (rfunc)
77  return rfunc();
78 
79  return kPluginType_Module;
80 }
81 
83 {
84  using PluginDestFunc = void (*)();
85  PluginDestFunc rfunc = QLibrary::resolve("mythplugin_destroy");
86 
87  if (rfunc)
88  rfunc();
89 }
90 
92 {
93  QString pluginprefix = GetPluginsDir();
94 
95  QDir filterDir(pluginprefix);
96 
97  filterDir.setFilter(QDir::Files | QDir::Readable);
98  QString filter = GetPluginsNameFilter();
99  filterDir.setNameFilters(QStringList(filter));
100 
101  if (filterDir.exists())
102  {
103  int prefixLength = filter.indexOf("*");
104  int suffixLength = filter.length() - prefixLength - 1;
105 
106  QStringList libraries = filterDir.entryList();
107  if (libraries.isEmpty())
108  LOG(VB_GENERAL, LOG_WARNING,
109  "No libraries in plugins directory " + filterDir.path());
110 
111  // coverity[auto_causes_copy]
112  for (auto library : qAsConst(libraries))
113  {
114  // pull out the base library name
115  library = library.right(library.length() - prefixLength);
116  library = library.left(library.length() - suffixLength);
117 
118  init_plugin(library);
119  }
120  }
121  else
122  LOG(VB_GENERAL, LOG_WARNING,
123  "No plugins directory " + filterDir.path());
124 }
125 
126 bool MythPluginManager::init_plugin(const QString &plugname)
127 {
128  QString newname = FindPluginName(plugname);
129 
130  if (!m_dict[newname])
131  {
132  m_dict.insert(newname, new MythPlugin(newname, plugname));
133  }
134 
135  int result = m_dict[newname]->init(MYTH_BINARY_VERSION);
136 
137  if (result == -1)
138  {
139  delete m_dict[newname];
140  m_dict.remove(newname);
141  LOG(VB_GENERAL, LOG_ERR,
142  QString("Unable to initialize plugin '%1'.") .arg(plugname));
143  return false;
144  }
145 
146  MythTranslation::load(plugname);
147 
148  switch (m_dict[newname]->type())
149  {
150  case kPluginType_Module:
151  default:
152  m_moduleMap[newname] = m_dict[newname];
153  break;
154  }
155 
156  return true;
157 }
158 
159 // return false on success, true on error
160 bool MythPluginManager::run_plugin(const QString &plugname)
161 {
162  QString newname = FindPluginName(plugname);
163 
164  if (!m_dict[newname] && !init_plugin(plugname))
165  {
166  LOG(VB_GENERAL, LOG_ALERT,
167  QString("Unable to run plugin '%1': not initialized")
168  .arg(plugname));
169  return true;
170  }
171 
172  bool res = m_dict[newname]->run() != 0;
173 
174  return res;
175 }
176 
177 // return false on success, true on error
178 bool MythPluginManager::config_plugin(const QString &plugname)
179 {
180  QString newname = FindPluginName(plugname);
181 
182  if (!m_dict[newname] && !init_plugin(plugname))
183  {
184  LOG(VB_GENERAL, LOG_ALERT,
185  QString("Unable to configure plugin '%1': not initialized")
186  .arg(plugname));
187  return true;
188  }
189 
190  bool res = m_dict[newname]->config() != 0;
191 
192  return res;
193 }
194 
195 bool MythPluginManager::destroy_plugin(const QString &plugname)
196 {
197  QString newname = FindPluginName(plugname);
198 
199  if (!m_dict[newname] && !init_plugin(plugname))
200  {
201  LOG(VB_GENERAL, LOG_ALERT,
202  QString("Unable to destroy plugin '%1': not initialized")
203  .arg(plugname));
204  return false;
205  }
206 
207  m_dict[newname]->destroy();
208  return true;
209 }
210 
211 MythPlugin *MythPluginManager::GetPlugin(const QString &plugname)
212 {
213  QString newname = FindPluginName(plugname);
214 
215  if (m_moduleMap.find(newname) == m_moduleMap.end())
216  return nullptr;
217 
218  return m_moduleMap[newname];
219 }
220 
222 {
223  for (auto *it : qAsConst(m_dict))
224  {
225  it->destroy();
226  delete it;
227  }
228 
229  m_dict.clear();
230  m_moduleMap.clear();
231 }
232 
234 {
235  QStringList ret;
236  for (auto *it : qAsConst(m_dict))
237  ret << it->getName();
238  return ret;
239 }
kPluginType_Module
@ kPluginType_Module
Definition: mythplugin.h:19
MythPlugin::run
int run(void)
Definition: mythplugin.cpp:42
MythPluginManager::run_plugin
bool run_plugin(const QString &plugname)
Definition: mythplugin.cpp:160
MythPlugin::type
MythPluginType type(void)
Definition: mythplugin.cpp:71
MythPlugin
Definition: mythplugin.h:22
mythplugin.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
GetPluginsDir
QString GetPluginsDir(void)
Definition: mythdirs.cpp:226
mythdirs.h
MythPluginManager::init_plugin
bool init_plugin(const QString &plugname)
Definition: mythplugin.cpp:126
mythversion.h
MythPlugin::destroy
void destroy(void)
Definition: mythplugin.cpp:82
MythPluginManager::m_dict
QHash< QString, MythPlugin * > m_dict
Definition: mythplugin.h:79
GetPluginsNameFilter
QString GetPluginsNameFilter(void)
Definition: mythdirs.cpp:288
mythlogging.h
compat.h
mythtranslation.h
MythPlugin::config
int config(void)
Definition: mythplugin.cpp:55
dlerror
const char * dlerror(void)
Definition: compat.h:156
MYTH_BINARY_VERSION
static constexpr const char * MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:15
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:54
MythPlugin::init
int init(const char *libversion)
Definition: mythplugin.cpp:21
MythPluginManager::config_plugin
bool config_plugin(const QString &plugname)
Definition: mythplugin.cpp:178
MythPluginManager::MythPluginManager
MythPluginManager()
Definition: mythplugin.cpp:91
MythPluginManager::m_moduleMap
QMap< QString, MythPlugin * > m_moduleMap
Definition: mythplugin.h:81
mythcorecontext.h
dlopen
#define dlopen(x, y)
Definition: compat.h:150
MythPluginManager::GetPlugin
MythPlugin * GetPlugin(const QString &plugname)
Definition: mythplugin.cpp:211
MythPluginManager::EnumeratePlugins
QStringList EnumeratePlugins(void)
Definition: mythplugin.cpp:233
MythCoreContext::ClearSettingsCache
void ClearSettingsCache(const QString &myKey=QString(""))
Definition: mythcorecontext.cpp:826
FindPluginName
QString FindPluginName(const QString &plugname)
Definition: mythdirs.cpp:293
MythPluginManager::DestroyAllPlugins
void DestroyAllPlugins()
Definition: mythplugin.cpp:221
MythTranslation::load
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
Definition: mythtranslation.cpp:37
RTLD_LAZY
#define RTLD_LAZY
Definition: compat.h:149
MythPluginManager::destroy_plugin
bool destroy_plugin(const QString &plugname)
Definition: mythplugin.cpp:195
MythPluginType
MythPluginType
Definition: mythplugin.h:18