MythTV  0.26-pre
mythplugin.cpp
Go to the documentation of this file.
00001 // C includes
00002 #ifndef USING_MINGW
00003 #include <dlfcn.h>
00004 #else
00005 #include "compat.h"
00006 #endif
00007 
00008 // Qt includes
00009 #include <QDir>
00010 
00011 // MythTV includes
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     // Commented out because it causes segfaults... dtk 2008-10-08
00032     //if (isLoaded())
00033     //    unload();
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             // pull out the base library name
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 // return false on success, true on error
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 // return false on success, true on error
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     // This needs to hit a db table for persistant ordering
00294     // For now, just use whatever order the map iterator returns
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends