void PluginCache::scanPluginFiles() { std::set<std::string> foundBinFiles; for (std::list<std::string>::iterator paths= _pluginPath.begin(); paths != _pluginPath.end(); paths++) { scanDirectory(foundBinFiles, *paths, _nonrecursePath.find(*paths) == _nonrecursePath.end()); } std::list<PluginBinary *>::iterator i=_binaries.begin(); while (i!=_binaries.end()) { PluginBinary *pb = *i; if (foundBinFiles.find(pb->getFilePath()) == foundBinFiles.end()) { // the binary was in the cache, but was not on the path _dirty = true; i = _binaries.erase(i); delete pb; } else { bool binChanged = pb->hasBinaryChanged(); // the binary was in the cache, but the binary has changed and thus we need to reload if (binChanged) { pb->loadPluginInfo(this); _dirty = true; } for (int j=0;j<pb->getNPlugins();j++) { Plugin *plug = &pb->getPlugin(j); APICache::PluginAPICacheI &api = plug->getApiHandler(); if (binChanged) { api.loadFromPlugin(plug); } std::string reason; if (api.pluginSupported(plug, reason)) { _plugins.push_back(plug); api.confirmPlugin(plug); } else { std::cerr << "ignoring plugin " << plug->getIdentifier() << " as unsupported (" << reason << ")" << std::endl; } } i++; } } }
void PluginCache::writePluginCache(std::ostream &os) const { #ifdef CACHE_DEBUG printf("writing pluginCache with version = %s\n", _cacheVersion.c_str()); #endif os << "<cache version=\"" << _cacheVersion << "\">\n"; for (std::list<PluginBinary *>::const_iterator i=_binaries.begin();i!=_binaries.end();i++) { PluginBinary *b = *i; os << "<bundle>\n"; os << " <binary " << XML::attribute("bundle_path", b->getBundlePath()) << XML::attribute("path", b->getFilePath()) << XML::attribute("mtime", int(b->getFileModificationTime())) << XML::attribute("size", int(b->getFileSize())) << "/>\n"; for (int j=0;j<b->getNPlugins();j++) { Plugin *p = &b->getPlugin(j); os << " <plugin " << XML::attribute("name", p->getRawIdentifier()) << XML::attribute("index", p->getIndex()) << XML::attribute("api", p->getPluginApi()) << XML::attribute("api_version", p->getApiVersion()) << XML::attribute("major_version", p->getVersionMajor()) << XML::attribute("minor_version", p->getVersionMinor()) << ">\n"; const APICache::PluginAPICacheI &api = p->getApiHandler(); os << " <apiproperties>\n"; api.saveXML(p, os); os << " </apiproperties>\n"; os << " </plugin>\n"; } os << "</bundle>\n"; } os << "</cache>\n"; }
void PluginCache::scanDirectory(std::set<std::string> &foundBinFiles, const std::string &dir, bool recurse) { #ifdef CACHE_DEBUG printf("looking in %s for plugins\n", dir.c_str()); #endif #if defined (WINDOWS) WIN32_FIND_DATA findData; HANDLE findHandle; #else DIR *d = opendir(dir.c_str()); if (!d) { return; } #endif _pluginDirs.push_back(dir.c_str()); #if defined (UNIX) while (dirent *de = readdir(d)) #elif defined (WINDOWS) findHandle = FindFirstFile((dir + "\\*").c_str(), &findData); if (findHandle == INVALID_HANDLE_VALUE) { return; } while (1) #endif { #if defined (UNIX) std::string name = de->d_name; bool isdir = true; #else std::string name = findData.cFileName; bool isdir = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; #endif if (name.find(".ofx.bundle") != std::string::npos) { std::string barename = name.substr(0, name.length() - strlen(".bundle")); std::string bundlename = dir + DIRSEP + name; std::string binpath = dir + DIRSEP + name + DIRSEP "Contents" DIRSEP + ARCHSTR + DIRSEP + barename; // don't insert binpath yet, do it later because of Mac OS X Universal stuff //foundBinFiles.insert(binpath); #if defined(__APPLE__) && (defined(__x86_64) || defined(__x86_64__)) /* From the OpenFX specification: MacOS-x86-64 - for Apple Macintosh OS X, specifically on intel x86 CPUs running AMD's 64 bit extensions. 64 bit host applications should check this first, and if it doesn't exist or is empty, fall back to "MacOS" looking for a universal binary. */ std::string binpath_universal = dir + DIRSEP + name + DIRSEP "Contents" DIRSEP + "MacOS" + DIRSEP + barename; if (_knownBinFiles.find(binpath_universal) != _knownBinFiles.end()) { binpath = binpath_universal; } #endif if (_knownBinFiles.find(binpath) == _knownBinFiles.end()) { #ifdef CACHE_DEBUG printf("found non-cached binary %s\n", binpath.c_str()); #endif _dirty = true; // the binary was not in the cache PluginBinary *pb = 0; #if defined(__x86_64) || defined(__x86_64__) pb = new PluginBinary(binpath, bundlename, this); # if defined(__APPLE__) if (pb->isInvalid()) { // fallback to "MacOS" delete pb; binpath = binpath_universal; pb = new PluginBinary(binpath, bundlename, this); } # endif #else pb = new PluginBinary(binpath, bundlename, this); #endif _binaries.push_back(pb); _knownBinFiles.insert(binpath); foundBinFiles.insert(binpath); for (int j=0;j<pb->getNPlugins();j++) { Plugin *plug = &pb->getPlugin(j); const APICache::PluginAPICacheI &api = plug->getApiHandler(); api.loadFromPlugin(plug); } } else { #ifdef CACHE_DEBUG printf("found cached binary %s\n", binpath.c_str()); #endif } // insert final path (universal or not) in the list of found files foundBinFiles.insert(binpath); } else { if (isdir && (recurse && name[0] != '@' && name != "." && name != "..")) { scanDirectory(foundBinFiles, dir + DIRSEP + name, recurse); } } #if defined(WINDOWS) int rval = FindNextFile(findHandle, &findData); if (rval == 0) { break; } #endif } #if defined(UNIX) closedir(d); #else FindClose(findHandle); #endif }
void PluginCache::scanDirectory(std::set<std::string> &foundBinFiles, const std::string &dir, bool recurse) { #ifdef CACHE_DEBUG printf("looking in %s for plugins\n", dir.c_str()); #endif #if defined (WINDOWS) WIN32_FIND_DATA findData; HANDLE findHandle; #else DIR *d = opendir(dir.c_str()); if (!d) { return; } #endif _pluginDirs.push_back(dir.c_str()); #if defined (UNIX) while (dirent *de = readdir(d)) #elif defined (WINDOWS) findHandle = FindFirstFile((dir + "\\*").c_str(), &findData); if (findHandle == INVALID_HANDLE_VALUE) { return; } while (1) #endif { #if defined (UNIX) std::string name = de->d_name; bool isdir = true; #else std::string name = findData.cFileName; bool isdir = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; #endif if (name.find(".ofx.bundle") != std::string::npos) { std::string barename = name.substr(0, name.length() - strlen(".bundle")); std::string bundlename = dir + DIRSEP + name; std::string binpath = dir + DIRSEP + name + DIRSEP "Contents" DIRSEP + ARCHSTR + DIRSEP + barename; foundBinFiles.insert(binpath); if (_knownBinFiles.find(binpath) == _knownBinFiles.end()) { #ifdef CACHE_DEBUG printf("found non-cached binary %s\n", binpath.c_str()); #endif _dirty = true; // the binary was not in the cache PluginBinary *pb = new PluginBinary(binpath, bundlename, this); _binaries.push_back(pb); _knownBinFiles.insert(binpath); for (int j=0;j<pb->getNPlugins();j++) { Plugin *plug = &pb->getPlugin(j); const APICache::PluginAPICacheI &api = plug->getApiHandler(); api.loadFromPlugin(plug); } } else { #ifdef CACHE_DEBUG printf("found cached binary %s\n", binpath.c_str()); #endif } } else { if (isdir && (recurse && name[0] != '@' && name != "." && name != "..")) { scanDirectory(foundBinFiles, dir + DIRSEP + name, recurse); } } #if defined(WINDOWS) int rval = FindNextFile(findHandle, &findData); if (rval == 0) { break; } #endif } #if defined(UNIX) closedir(d); #else FindClose(findHandle); #endif }