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