diff options
Diffstat (limited to 'noatun/library/pluginloader.cpp')
-rw-r--r-- | noatun/library/pluginloader.cpp | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/noatun/library/pluginloader.cpp b/noatun/library/pluginloader.cpp new file mode 100644 index 00000000..c367228a --- /dev/null +++ b/noatun/library/pluginloader.cpp @@ -0,0 +1,366 @@ +#include <qfile.h> +#include <kglobal.h> +#include <qdir.h> +#include <ksimpleconfig.h> +#include <kstandarddirs.h> +#include <knotifyclient.h> +#include <klocale.h> +#include <kurl.h> +#include <pluginloader.h> +#include <plugin.h> +#include <kdebug.h> + +bool operator ==(const NoatunLibraryInfo &a, const NoatunLibraryInfo &b) +{ + // Feels like cheating, doesn't it? + return a.specfile == b.specfile; +} + +LibraryLoader::LibraryLoader() : mPlaylist(0) +{ +} + +LibraryLoader::~LibraryLoader() +{ + QValueList<NoatunLibraryInfo> l; + + l = loaded(); + for(QValueList<NoatunLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i) + { + if((*i).type != "userinterface" && (*i).type != "playlist" && (*i).type != "systray") + { + removeNow((*i).specfile); + } + } + + l = loaded(); + for(QValueList<NoatunLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i) + { + if((*i).type == "userinterface") + { + removeNow((*i).specfile); + } + } + + l = loaded(); + for(QValueList<NoatunLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i) + { + removeNow((*i).specfile); + } +} + +QValueList<NoatunLibraryInfo> LibraryLoader::available() const +{ + QValueList<NoatunLibraryInfo> items; + QStringList files=KGlobal::dirs()->findAllResources("appdata", "*.plugin", false, true); + for (QStringList::Iterator i=files.begin(); i!=files.end(); ++i) + items.append(getInfo(*i)); + + return items; +} + +QPtrList<Plugin> LibraryLoader::plugins() const +{ + QPtrList<Plugin> list; + for (QDictIterator<LibraryLoader::PluginLibrary> i(mLibHash); i.current(); ++i) + list.append(i.current()->plugin); + return list; +} + +bool LibraryLoader::loadAll() +{ + KConfig *config=KGlobal::config(); + config->setGroup(""); + QStringList modules = config->readListEntry("Modules"); + return loadAll(modules); +} + +bool LibraryLoader::loadAll(const QStringList &modules) +{ + // Session management... + for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i) + { + NoatunLibraryInfo info=getInfo(*i); + if (!info.type.contains("sm")) + continue; + loadSO(*i); + } + + // load all the playlists in the first + for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i) + { + NoatunLibraryInfo info=getInfo(*i); + if (!info.type.contains("playlist")) + continue; + loadSO(*i); + } + + if (!mPlaylist) + { + kdWarning(66666) << "No playlist plugin loaded, defaulting to splitplaylist" << endl; + if (!loadSO("splitplaylist.plugin")) + return false; + } + + // load all the user interfaces now + for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i) + { + NoatunLibraryInfo info=getInfo(*i); + if (!info.type.contains("userinterface")) + continue; + loadSO(*i); + } + + if (!loadedByType("userinterface").count()) + { + kdWarning(66666) << "No userinterface plugin loaded, defaulting to excellent" << endl; + if (!loadSO("excellent.plugin")) + return false; + } + + for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i) + { + NoatunLibraryInfo info=getInfo(*i); + if((!info.type.contains("playlist")) + && (!info.type.contains("userinterface")) + && (!info.type.contains("sm"))) + { + loadSO(*i); + } + } + + return true; +} + +NoatunLibraryInfo LibraryLoader::getInfo(const QString &spec) const +{ + NoatunLibraryInfo info; + QString specPath = (spec[0]=='/') ? spec : KGlobal::dirs()->findResource("appdata", spec); + if (!QFile::exists(specPath)) + return info; + KSimpleConfig file(specPath); + if (spec.find('/')>=0) + info.specfile=KURL(spec).fileName(); + else + info.specfile=spec; + info.filename=file.readPathEntry("Filename"); + info.author=file.readEntry("Author"); + info.site=file.readEntry("Site"); + info.email=file.readEntry("Email"); + info.type=file.readEntry("Type"); + info.name=file.readEntry("Name"); + info.comment=file.readEntry("Comment"); + info.require=file.readListEntry("Require"); + info.license=file.readEntry("License"); + return info; +} + +bool LibraryLoader::isLoaded(const QString &spec) const +{ + PluginLibrary *lib=mLibHash[spec]; + if (!lib) return false; + return lib->plugin; +} + +bool LibraryLoader::loadSO(const QString &spec) +{ + if(!isLoaded(spec)) + { + NoatunLibraryInfo info = getInfo(spec); + if (info.specfile != spec) + return false; + + for (QStringList::ConstIterator it = info.require.begin(); it != info.require.end(); ++it) + loadSO(*it); + + // get the library loader instance + KLibLoader *loader = KLibLoader::self(); + + PluginLibrary *listitem=mLibHash[spec]; + + if (!listitem) + { + QString filename = KGlobal::dirs()->findResource("module", info.filename); + KLibrary *lib = loader->library(QFile::encodeName(filename)); + if (!lib) + return false; + listitem=new PluginLibrary; + listitem->library=lib; + mLibHash.insert(spec, listitem); + } + + void *create=listitem->library->symbol("create_plugin"); + if (!create) + return false; + + Plugin* (*plugInStart)(); + plugInStart=(Plugin* (*)()) create; + listitem->plugin=plugInStart(); + + if (info.type.contains("playlist")) + { + //kdDebug(66666) << k_funcinfo << "Assigning mPlaylist to " << info.name << endl; + mPlaylist=listitem->plugin->playlist(); + } + listitem->plugin->init(); + + return true; + } + else + return false; +} + +void LibraryLoader::add(const QString &spec) +{ + PluginLibrary *lib=mLibHash[spec]; + if (lib) + if (lib->plugin) return; + + loadSO(spec); +} + +void LibraryLoader::setModules(const QStringList &mods) +{ + KConfig *config=KGlobal::config(); + config->setGroup(0); + config->writeEntry("Modules", mods); + config->sync(); +} + +bool LibraryLoader::remove(const QString& spec, bool terminateOnLastUI) +{ + bool SystrayPluginEnabled=false; + + NoatunLibraryInfo info = getInfo(spec); + // exit if this is the last UI + if (info.type=="userinterface" && terminateOnLastUI) + { + QValueList<NoatunLibraryInfo> l=loaded(); + + // Iterate over other plugins + for (QValueList<NoatunLibraryInfo>::Iterator i=l.begin(); i!=l.end(); ++i) + { + // Is this a UI plugin? + if ((*i).specfile!=spec && (*i).type=="userinterface") + { + // Good, we don't have to exit + removeNow(spec); + return true; + } + else if((*i).type=="systray") // Is there a Systray plugin? + { + SystrayPluginEnabled=true; + } + } + + // Don't terminate, when there is a systray plugin. + if(SystrayPluginEnabled) + { + napp->toggleInterfaces(); + return true; + } + else + { + // No other UIs, terminate + kapp->exit(); + } + } + else if (info.type=="playlist") + { + //kdWarning(66666) << "Unloading playlist, this might be dangerous" << endl; + mPlaylist=0; + } + + removeNow(spec); + return true; +} + +bool LibraryLoader::remove(const QString &spec) +{ + remove(spec, true); + return true; +} + +bool LibraryLoader::remove(const PluginLibrary *pl) +{ + for (QDictIterator<PluginLibrary> i(mLibHash); i.current(); ++i) + { + if (i.current()==pl) + return remove(i.currentKey()); + } + return false; +} + +bool LibraryLoader::remove(const Plugin *plugin) +{ + for (QDictIterator<PluginLibrary> i(mLibHash); i.current(); ++i) + { + if (i.current()->plugin==plugin) + return remove(i.currentKey()); + } + return false; + +} + +Playlist *LibraryLoader::playlist() const +{ + // playlist should never be NULL when this method is called + Q_ASSERT(mPlaylist); + return mPlaylist; +} + +QValueList<NoatunLibraryInfo> LibraryLoader::loaded() const +{ + QValueList<NoatunLibraryInfo> items; + + for (QDictIterator<PluginLibrary> i(mLibHash); i.current(); ++i) + if (isLoaded(i.currentKey())) + items.append(getInfo(i.currentKey())); + + return items; +} + +QValueList<NoatunLibraryInfo> LibraryLoader::loadedByType(const QString &type) const +{ + QValueList<NoatunLibraryInfo> items; + + for (QDictIterator<PluginLibrary> i(mLibHash); i.current(); ++i) + { + if (isLoaded(i.currentKey())) + { + NoatunLibraryInfo info = getInfo(i.currentKey()); + if (info.type.contains(type)) + items.append(info); + } + } + + return items; +} + +void LibraryLoader::removeNow(const QString &spec) +{ + NoatunLibraryInfo info = getInfo(spec); + if (info.specfile == spec) + { + QValueList<NoatunLibraryInfo> l = loaded(); + for (QValueList<NoatunLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i) + { + for (QStringList::ConstIterator it = (*i).require.begin(); it != (*i).require.end(); ++it) + { + if (*it == spec) + removeNow((*i).specfile); + } + } + } + + PluginLibrary *lib=mLibHash[spec]; + + if (!lib) return; + + delete lib->plugin; + lib->plugin=0; + mLibHash.remove(spec); + delete lib; +} + + |