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