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  for (auto library : qAsConst(libraries))
112  {
113  // pull out the base library name
114  library = library.right(library.length() - prefixLength);
115  library = library.left(library.length() - suffixLength);
116 
117  init_plugin(library);
118  }
119  }
120  else
121  LOG(VB_GENERAL, LOG_WARNING,
122  "No plugins directory " + filterDir.path());
123 }
124 
125 bool MythPluginManager::init_plugin(const QString &plugname)
126 {
127  QString newname = FindPluginName(plugname);
128 
129  if (!m_dict[newname])
130  {
131  m_dict.insert(newname, new MythPlugin(newname, plugname));
132  }
133 
134  int result = m_dict[newname]->init(MYTH_BINARY_VERSION);
135 
136  if (result == -1)
137  {
138  delete m_dict[newname];
139  m_dict.remove(newname);
140  LOG(VB_GENERAL, LOG_ERR,
141  QString("Unable to initialize plugin '%1'.") .arg(plugname));
142  return false;
143  }
144 
145  MythTranslation::load(plugname);
146 
147  switch (m_dict[newname]->type())
148  {
149  case kPluginType_Module:
150  default:
151  m_moduleMap[newname] = m_dict[newname];
152  break;
153  }
154 
155  return true;
156 }
157 
158 // return false on success, true on error
159 bool MythPluginManager::run_plugin(const QString &plugname)
160 {
161  QString newname = FindPluginName(plugname);
162 
163  if (!m_dict[newname] && !init_plugin(plugname))
164  {
165  LOG(VB_GENERAL, LOG_ALERT,
166  QString("Unable to run plugin '%1': not initialized")
167  .arg(plugname));
168  return true;
169  }
170 
171  bool res = m_dict[newname]->run() != 0;
172 
173  return res;
174 }
175 
176 // return false on success, true on error
177 bool MythPluginManager::config_plugin(const QString &plugname)
178 {
179  QString newname = FindPluginName(plugname);
180 
181  if (!m_dict[newname] && !init_plugin(plugname))
182  {
183  LOG(VB_GENERAL, LOG_ALERT,
184  QString("Unable to configure plugin '%1': not initialized")
185  .arg(plugname));
186  return true;
187  }
188 
189  bool res = m_dict[newname]->config() != 0;
190 
191  return res;
192 }
193 
194 bool MythPluginManager::destroy_plugin(const QString &plugname)
195 {
196  QString newname = FindPluginName(plugname);
197 
198  if (!m_dict[newname] && !init_plugin(plugname))
199  {
200  LOG(VB_GENERAL, LOG_ALERT,
201  QString("Unable to destroy plugin '%1': not initialized")
202  .arg(plugname));
203  return false;
204  }
205 
206  m_dict[newname]->destroy();
207  return true;
208 }
209 
210 MythPlugin *MythPluginManager::GetPlugin(const QString &plugname)
211 {
212  QString newname = FindPluginName(plugname);
213 
214  if (m_moduleMap.find(newname) == m_moduleMap.end())
215  return nullptr;
216 
217  return m_moduleMap[newname];
218 }
219 
221 {
222  for (auto *it : qAsConst(m_dict))
223  {
224  it->destroy();
225  delete it;
226  }
227 
228  m_dict.clear();
229  m_moduleMap.clear();
230 }
231 
233 {
234  QStringList ret;
235  for (auto *it : qAsConst(m_dict))
236  ret << it->getName();
237  return ret;
238 }
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:159
MythPlugin::type
MythPluginType type(void)
Definition: mythplugin.cpp:71
MythPlugin
Definition: mythplugin.h:23
mythplugin.h
arg
arg(title).arg(filename).arg(doDelete))
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
GetPluginsDir
QString GetPluginsDir(void)
Definition: mythdirs.cpp:226
mythdirs.h
MythPluginManager::init_plugin
bool init_plugin(const QString &plugname)
Definition: mythplugin.cpp:125
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:239
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:56
MythPlugin::init
int init(const char *libversion)
Definition: mythplugin.cpp:21
MythPluginManager::config_plugin
bool config_plugin(const QString &plugname)
Definition: mythplugin.cpp:177
MYTH_BINARY_VERSION
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:15
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:234
MythPluginManager::GetPlugin
MythPlugin * GetPlugin(const QString &plugname)
Definition: mythplugin.cpp:210
MythPluginManager::EnumeratePlugins
QStringList EnumeratePlugins(void)
Definition: mythplugin.cpp:232
MythCoreContext::ClearSettingsCache
void ClearSettingsCache(const QString &myKey=QString(""))
Definition: mythcorecontext.cpp:845
FindPluginName
QString FindPluginName(const QString &plugname)
Definition: mythdirs.cpp:293
MythPluginManager::DestroyAllPlugins
void DestroyAllPlugins()
Definition: mythplugin.cpp:220
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:233
MythPluginManager::destroy_plugin
bool destroy_plugin(const QString &plugname)
Definition: mythplugin.cpp:194
MythPluginType
MythPluginType
Definition: mythplugin.h:18