#include #include #include #include #include #include #include #include #include #include #include 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() { TQValueList l; l = loaded(); for(TQValueList::Iterator i = l.begin(); i != l.end(); ++i) { if((*i).type != "userinterface" && (*i).type != "playlist" && (*i).type != "systray") { removeNow((*i).specfile); } } l = loaded(); for(TQValueList::Iterator i = l.begin(); i != l.end(); ++i) { if((*i).type == "userinterface") { removeNow((*i).specfile); } } l = loaded(); for(TQValueList::Iterator i = l.begin(); i != l.end(); ++i) { removeNow((*i).specfile); } } TQValueList LibraryLoader::available() const { TQValueList items; TQStringList files=TDEGlobal::dirs()->findAllResources("appdata", "*.plugin", false, true); for (TQStringList::Iterator i=files.begin(); i!=files.end(); ++i) items.append(getInfo(*i)); return items; } TQPtrList LibraryLoader::plugins() const { TQPtrList list; for (TQDictIterator i(mLibHash); i.current(); ++i) list.append(i.current()->plugin); return list; } bool LibraryLoader::loadAll() { TDEConfig *config=TDEGlobal::config(); config->setGroup(""); TQStringList modules = config->readListEntry("Modules"); return loadAll(modules); } bool LibraryLoader::loadAll(const TQStringList &modules) { // Session management... for(TQStringList::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(TQStringList::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(TQStringList::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(TQStringList::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 TQString &spec) const { NoatunLibraryInfo info; TQString specPath = (spec[0]=='/') ? spec : TDEGlobal::dirs()->findResource("appdata", spec); if (!TQFile::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 TQString &spec) const { PluginLibrary *lib=mLibHash[spec]; if (!lib) return false; return lib->plugin; } bool LibraryLoader::loadSO(const TQString &spec) { if(!isLoaded(spec)) { NoatunLibraryInfo info = getInfo(spec); if (info.specfile != spec) return false; for (TQStringList::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) { TQString filename = TDEGlobal::dirs()->findResource("module", info.filename); KLibrary *lib = loader->library(TQFile::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 TQString &spec) { PluginLibrary *lib=mLibHash[spec]; if (lib) if (lib->plugin) return; loadSO(spec); } void LibraryLoader::setModules(const TQStringList &mods) { TDEConfig *config=TDEGlobal::config(); config->setGroup(0); config->writeEntry("Modules", mods); config->sync(); } bool LibraryLoader::remove(const TQString& spec, bool terminateOnLastUI) { bool SystrayPluginEnabled=false; NoatunLibraryInfo info = getInfo(spec); // exit if this is the last UI if (info.type=="userinterface" && terminateOnLastUI) { TQValueList l=loaded(); // Iterate over other plugins for (TQValueList::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 TQString &spec) { remove(spec, true); return true; } bool LibraryLoader::remove(const PluginLibrary *pl) { for (TQDictIterator i(mLibHash); i.current(); ++i) { if (i.current()==pl) return remove(i.currentKey()); } return false; } bool LibraryLoader::remove(const Plugin *plugin) { for (TQDictIterator 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; } TQValueList LibraryLoader::loaded() const { TQValueList items; for (TQDictIterator i(mLibHash); i.current(); ++i) if (isLoaded(i.currentKey())) items.append(getInfo(i.currentKey())); return items; } TQValueList LibraryLoader::loadedByType(const TQString &type) const { TQValueList items; for (TQDictIterator 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 TQString &spec) { NoatunLibraryInfo info = getInfo(spec); if (info.specfile == spec) { TQValueList l = loaded(); for (TQValueList::Iterator i = l.begin(); i != l.end(); ++i) { for (TQStringList::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; }