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