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