#ifndef OFX_PLUGIN_CACHE_H
#define OFX_PLUGIN_CACHE_H
#include <string>
#include <vector>
#include <list>
#include <set>
#include <iostream>
#include <stdio.h>
#include "expat.h"
#include "ofxCore.h"
#include "ofxhPropertySuite.h"
#include "ofxhPluginAPICache.h"
#include "ofxhBinary.h"
namespace OFX {
namespace Host {
class Host;
class PluginDesc;
class Plugin;
class PluginBinary;
class PluginCache;
class PluginDesc {
protected :
std::string _pluginApi; int _apiVersion;
std::string _identifier; std::string _rawIdentifier; int _versionMajor; int _versionMinor;
public:
const std::string &getPluginApi() const {
return _pluginApi;
}
int getApiVersion() const {
return _apiVersion;
}
const std::string &getIdentifier() const {
return _identifier;
}
const std::string &getRawIdentifier() const {
return _rawIdentifier;
}
int getVersionMajor() const {
return _versionMajor;
}
int getVersionMinor() const {
return _versionMinor;
}
PluginDesc() : _apiVersion(-1) {
}
virtual ~PluginDesc() {}
PluginDesc(const std::string &api,
int apiVersion,
const std::string &identifier,
const std::string &rawIdentifier,
int versionMajor,
int versionMinor)
: _pluginApi(api)
, _apiVersion(apiVersion)
, _identifier(identifier)
, _rawIdentifier(rawIdentifier)
, _versionMajor(versionMajor)
, _versionMinor(versionMinor)
{
}
PluginDesc(OfxPlugin *ofxPlugin) {
_pluginApi = ofxPlugin->pluginApi;
_apiVersion = ofxPlugin->apiVersion;
_rawIdentifier = ofxPlugin->pluginIdentifier;
_identifier = ofxPlugin->pluginIdentifier;
_versionMajor = ofxPlugin->pluginVersionMajor;
_versionMinor = ofxPlugin->pluginVersionMinor;
}
};
class Plugin : public PluginDesc {
private :
Plugin(const Plugin&) : PluginDesc() {} Plugin &operator= (const Plugin&) {return *this;}
protected :
PluginBinary *_binary; int _index; public :
Plugin();
PluginBinary *getBinary()
{
return _binary;
}
const PluginBinary *getBinary() const
{
return _binary;
}
int getIndex() const
{
return _index;
}
Plugin(PluginBinary *bin, int idx, OfxPlugin *o) : PluginDesc(o), _binary(bin), _index(idx)
{
}
Plugin(PluginBinary *bin, int idx, const std::string &api,
int apiVersion, const std::string &identifier,
const std::string &rawIdentifier,
int majorVersion, int minorVersion)
: PluginDesc(api, apiVersion, identifier, rawIdentifier, majorVersion, minorVersion)
, _binary(bin)
, _index(idx)
{
}
virtual ~Plugin() {
}
virtual APICache::PluginAPICacheI &getApiHandler() = 0;
bool trumps(Plugin *other) {
int myMajor = getVersionMajor();
int theirMajor = other->getVersionMajor();
int myMinor = getVersionMinor();
int theirMinor = other->getVersionMinor();
if (myMajor > theirMajor) {
return true;
}
if (myMajor == theirMajor && myMinor > theirMinor) {
return true;
}
return false;
}
};
class PluginHandle;
class PluginBinary {
friend class PluginHandle;
protected :
Binary _binary; std::string _filePath; std::string _bundlePath; std::vector<Plugin *> _plugins; time_t _fileModificationTime; off_t _fileSize; bool _binaryChanged;
public :
explicit PluginBinary(const std::string &file, const std::string &bundlePath, time_t mtime, off_t size)
: _binary(file)
, _filePath(file)
, _bundlePath(bundlePath)
, _fileModificationTime(mtime)
, _fileSize(size)
, _binaryChanged(false)
{
if (isInvalid()) {
return;
}
if (_fileModificationTime != _binary.getTime() || _fileSize != _binary.getSize()) {
_binaryChanged = true;
}
}
explicit PluginBinary(const std::string &file, const std::string &bundlePath, PluginCache *cache)
: _binary(file)
, _filePath(file)
, _bundlePath(bundlePath)
, _binaryChanged(false)
{
loadPluginInfo(cache);
}
virtual ~PluginBinary();
time_t getFileModificationTime() const {
return _fileModificationTime;
}
off_t getFileSize() {
return _fileSize;
}
const std::string &getFilePath() const {
return _filePath;
}
const std::string &getBundlePath() const {
return _bundlePath;
}
bool hasBinaryChanged() const {
return _binaryChanged;
}
bool isLoaded() const {
return _binary.isLoaded();
}
bool isInvalid() const {
return _binary.isInvalid();
}
void addPlugin(Plugin *pe) {
_plugins.push_back(pe);
}
void loadPluginInfo(PluginCache *);
int getNPlugins() const {return (int)_plugins.size(); }
Plugin &getPlugin(int idx) {return *_plugins[idx];}
const Plugin &getPlugin(int idx) const {return *_plugins[idx];}
};
class PluginHandle {
PluginBinary *_b;
OfxPlugin *_op;
public:
PluginHandle(Plugin *p, OFX::Host::Host *_host);
virtual ~PluginHandle();
OfxPlugin *getOfxPlugin() {
return _op;
}
OfxPlugin *operator->() {
return _op;
}
};
struct PluginCacheSupportedApi {
std::string api;
int minVersion;
int maxVersion;
APICache::PluginAPICacheI *handler;
PluginCacheSupportedApi(const std::string &_api, int _minVersion, int _maxVersion, APICache::PluginAPICacheI *_handler) :
api(_api), minVersion(_minVersion), maxVersion(_maxVersion), handler(_handler)
{
}
bool matches(const std::string &_api, int _version) const
{
if (_api == api && _version >= minVersion && _version <= maxVersion) {
return true;
}
return false;
}
};
class PluginCache {
protected :
OFX::Host::Property::PropSpec* _hostSpec;
std::list<std::string> _pluginPath; std::set<std::string> _nonrecursePath; std::list<std::string> _pluginDirs; std::list<PluginBinary *> _binaries; std::list<Plugin *> _plugins; std::set<std::string> _knownBinFiles;
PluginBinary *_xmlCurrentBinary;
Plugin *_xmlCurrentPlugin;
std::list<PluginCacheSupportedApi> _apiHandlers;
void scanDirectory(std::set<std::string> &foundBinFiles, const std::string &dir, bool recurse);
bool _ignoreCache;
std::string _cacheVersion;
bool _dirty;
bool _enablePluginSeek;
static PluginCache* gPluginCachePtr;
public:
PluginCache();
~PluginCache();
static PluginCache* getPluginCache();
static void clearPluginCache();
const std::list<std::string> &getPluginPath() {
return _pluginPath;
}
bool dirty() const {
return _dirty;
}
void addFileToPath(const std::string &f, bool recurse=true) {
_pluginPath.push_back(f);
if (!recurse) {
_nonrecursePath.insert(f);
}
}
void prependFileToPath(const std::string &f, bool recurse=true) {
_pluginPath.push_front(f);
if (!recurse) {
_nonrecursePath.insert(f);
}
}
void setPluginHostPath(const std::string &hostId);
void setCacheVersion(const std::string &cacheVersion) {
_cacheVersion = cacheVersion;
}
void readCache(std::istream &is);
std::string seekPluginFile(const std::string &baseName) const;
void setPluginSeekEnabled(bool enabled) { _enablePluginSeek = enabled; }
void scanPluginFiles();
void writePluginCache(std::ostream &os) const;
void elementBeginCallback(void *userData, const XML_Char *name, const XML_Char **attrs);
void elementCharCallback(void *userData, const XML_Char *data, int len);
void elementEndCallback(void *userData, const XML_Char *name);
void registerAPICache(const std::string &api, int min, int max, APICache::PluginAPICacheI *apiCache) {
_apiHandlers.push_back(PluginCacheSupportedApi(api, min, max, apiCache));
}
APICache::PluginAPICacheI* findApiHandler(const std::string &api, int apiver);
const std::list<Plugin *> &getPlugins() const {
return _plugins;
}
};
}
}
#endif