00001
00002 #ifndef USING_MINGW
00003 #include <dlfcn.h>
00004 #else
00005 #include "compat.h"
00006 #endif
00007
00008
00009 #include <QDir>
00010
00011
00012 #include "mythplugin.h"
00013 #include "mythcontext.h"
00014 #include "mythtranslation.h"
00015
00016 #include "mythdirs.h"
00017 #include "mythversion.h"
00018 #include "mythlogging.h"
00019
00020 using namespace std;
00021
00022 MythPlugin::MythPlugin(const QString &libname, const QString &plugname)
00023 : QLibrary(libname), m_plugName(plugname)
00024 {
00025 enabled = true;
00026 position = 0;
00027 }
00028
00029 MythPlugin::~MythPlugin()
00030 {
00031
00032
00033
00034 }
00035
00036 int MythPlugin::init(const char *libversion)
00037 {
00038 typedef int (*PluginInitFunc)(const char *);
00039 PluginInitFunc ifunc = (PluginInitFunc)QLibrary::resolve("mythplugin_init");
00040
00041 if (ifunc)
00042 return ifunc(libversion);
00043
00044 QString error_msg(dlerror());
00045 if (error_msg.isEmpty())
00046 {
00047 QByteArray libname = QLibrary::fileName().toAscii();
00048 (void)dlopen(libname.constData(), RTLD_LAZY);
00049 error_msg = dlerror();
00050 }
00051
00052 LOG(VB_GENERAL, LOG_EMERG, QString("MythPlugin::init() dlerror: %1")
00053 .arg(error_msg));
00054
00055 return -1;
00056 }
00057
00058 int MythPlugin::run(void)
00059 {
00060 typedef int (*PluginRunFunc)();
00061
00062 int rVal = -1;
00063 PluginRunFunc rfunc = (PluginRunFunc)QLibrary::resolve("mythplugin_run");
00064
00065 if (rfunc)
00066 rVal = rfunc();
00067
00068 return rVal;
00069 }
00070
00071 int MythPlugin::config(void)
00072 {
00073 typedef int (*PluginConfigFunc)();
00074
00075 int rVal = -1;
00076 PluginConfigFunc rfunc = (PluginConfigFunc)QLibrary::resolve(
00077 "mythplugin_config");
00078
00079 if (rfunc)
00080 {
00081 rVal = rfunc();
00082 gCoreContext->ClearSettingsCache();
00083 }
00084
00085 return rVal;
00086 }
00087
00088 MythPluginType MythPlugin::type(void)
00089 {
00090 typedef MythPluginType (*PluginTypeFunc)();
00091 PluginTypeFunc rfunc = (PluginTypeFunc)QLibrary::resolve("mythplugin_type");
00092
00093 if (rfunc)
00094 return rfunc();
00095
00096 return kPluginType_Module;
00097 }
00098
00099 void MythPlugin::destroy(void)
00100 {
00101 typedef void (*PluginDestFunc)();
00102 PluginDestFunc rfunc = (PluginDestFunc)QLibrary::resolve("mythplugin_destroy");
00103
00104 if (rfunc)
00105 rfunc();
00106 }
00107
00108 int MythPlugin::setupMenuPlugin(void)
00109 {
00110 typedef int (*PluginSetup)();
00111 PluginSetup rfunc = (PluginSetup)QLibrary::resolve("mythplugin_setupMenu");
00112
00113 if (rfunc)
00114 return rfunc();
00115
00116 return -1;
00117 }
00118
00119 void MythPlugin::drawMenuPlugin(QPainter *painter, int x, int y, int w, int h)
00120 {
00121 typedef void (*PluginDrawMenu)(QPainter *, int, int, int, int);
00122 PluginDrawMenu rfunc = (PluginDrawMenu)QLibrary::resolve("mythplugin_drawMenu");
00123
00124 if (rfunc)
00125 rfunc(painter, x, y, w, h);
00126 }
00127
00128 MythPluginManager::MythPluginManager()
00129 {
00130 QString pluginprefix = GetPluginsDir();
00131
00132 QDir filterDir(pluginprefix);
00133
00134 filterDir.setFilter(QDir::Files | QDir::Readable);
00135 QString filter = GetPluginsNameFilter();
00136 filterDir.setNameFilters(QStringList(filter));
00137
00138 gContext->SetDisableLibraryPopup(true);
00139
00140 if (filterDir.exists())
00141 {
00142 int prefixLength = filter.indexOf("*");
00143 int suffixLength = filter.length() - prefixLength - 1;
00144
00145 QStringList libraries = filterDir.entryList();
00146 if (libraries.isEmpty())
00147 LOG(VB_GENERAL, LOG_WARNING,
00148 "No libraries in plugins directory " + filterDir.path());
00149
00150 for (QStringList::iterator i = libraries.begin(); i != libraries.end();
00151 ++i)
00152 {
00153 QString library = *i;
00154
00155
00156 library = library.right(library.length() - prefixLength);
00157 library = library.left(library.length() - suffixLength);
00158
00159 init_plugin(library);
00160 }
00161 }
00162 else
00163 LOG(VB_GENERAL, LOG_WARNING,
00164 "No plugins directory " + filterDir.path());
00165
00166 gContext->SetDisableLibraryPopup(false);
00167
00168 orderMenuPlugins();
00169 }
00170
00171 MythPluginManager::~MythPluginManager()
00172 {
00173 }
00174
00175 bool MythPluginManager::init_plugin(const QString &plugname)
00176 {
00177 QString newname = FindPluginName(plugname);
00178
00179 if (!m_dict[newname])
00180 {
00181 m_dict.insert(newname, new MythPlugin(newname, plugname));
00182 }
00183
00184 int result = m_dict[newname]->init(MYTH_BINARY_VERSION);
00185
00186 if (result == -1)
00187 {
00188 delete m_dict[newname];
00189 m_dict.remove(newname);
00190 LOG(VB_GENERAL, LOG_ERR,
00191 QString("Unable to initialize plugin '%1'.") .arg(plugname));
00192 return false;
00193 }
00194
00195 MythTranslation::load(plugname);
00196
00197 switch (m_dict[newname]->type())
00198 {
00199 case kPluginType_MenuPlugin:
00200 menuPluginMap[newname] = m_dict[newname];
00201 break;
00202 case kPluginType_Module:
00203 default:
00204 moduleMap[newname] = m_dict[newname];
00205 break;
00206 }
00207
00208 return true;
00209 }
00210
00211
00212 bool MythPluginManager::run_plugin(const QString &plugname)
00213 {
00214 QString newname = FindPluginName(plugname);
00215
00216 if (!m_dict[newname] && !init_plugin(plugname))
00217 {
00218 LOG(VB_GENERAL, LOG_ALERT,
00219 QString("Unable to run plugin '%1': not initialized")
00220 .arg(plugname));
00221 return true;
00222 }
00223
00224 bool res = m_dict[newname]->run();
00225
00226 return res;
00227 }
00228
00229
00230 bool MythPluginManager::config_plugin(const QString &plugname)
00231 {
00232 QString newname = FindPluginName(plugname);
00233
00234 if (!m_dict[newname] && !init_plugin(plugname))
00235 {
00236 LOG(VB_GENERAL, LOG_ALERT,
00237 QString("Unable to configure plugin '%1': not initialized")
00238 .arg(plugname));
00239 return true;
00240 }
00241
00242 bool res = m_dict[newname]->config();
00243
00244 return res;
00245 }
00246
00247 bool MythPluginManager::destroy_plugin(const QString &plugname)
00248 {
00249 QString newname = FindPluginName(plugname);
00250
00251 if (!m_dict[newname] && !init_plugin(plugname))
00252 {
00253 LOG(VB_GENERAL, LOG_ALERT,
00254 QString("Unable to destroy plugin '%1': not initialized")
00255 .arg(plugname));
00256 return false;
00257 }
00258
00259 m_dict[newname]->destroy();
00260 return true;
00261 }
00262
00263 MythPlugin *MythPluginManager::GetPlugin(const QString &plugname)
00264 {
00265 QString newname = FindPluginName(plugname);
00266
00267 if (moduleMap.find(newname) == moduleMap.end())
00268 return NULL;
00269
00270 return moduleMap[newname];
00271 }
00272
00273 MythPlugin *MythPluginManager::GetMenuPlugin(const QString &plugname)
00274 {
00275 QString newname = FindPluginName(plugname);
00276
00277 if (menuPluginMap.find(newname) == menuPluginMap.end())
00278 return NULL;
00279
00280 return menuPluginMap[newname];
00281 }
00282
00283 MythPlugin *MythPluginManager::GetMenuPluginAt(int pos)
00284 {
00285 if ((uint)pos >= menuPluginList.size())
00286 return NULL;
00287
00288 return menuPluginList[pos];
00289 }
00290
00291 void MythPluginManager::orderMenuPlugins(void)
00292 {
00293
00294
00295
00296 menuPluginList.clear();
00297
00298 QMap<QString, MythPlugin *>::iterator iter = menuPluginMap.begin();
00299 for (; iter != menuPluginMap.end(); ++iter)
00300 {
00301 if ((*iter)->isEnabled())
00302 menuPluginList.push_back(*iter);
00303 }
00304 }
00305
00306 void MythPluginManager::DestroyAllPlugins(void)
00307 {
00308 QHash<QString, MythPlugin*>::iterator it = m_dict.begin();
00309 for (; it != m_dict.end(); ++it)
00310 {
00311 (*it)->destroy();
00312 delete *it;
00313 }
00314
00315 m_dict.clear();
00316 moduleMap.clear();
00317 menuPluginMap.clear();
00318 menuPluginList.clear();
00319 }
00320
00321 QStringList MythPluginManager::EnumeratePlugins(void)
00322 {
00323 QStringList ret;
00324 QHash<QString, MythPlugin*>::const_iterator it = m_dict.begin();
00325 for (; it != m_dict.end(); ++it)
00326 ret << (*it)->getName();
00327 return ret;
00328 }
00329