Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tpluginmanager.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include "tlogger.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// QUALE DI QUESTI SERVE VERAMENTE??
Toshihiro Shimizu 890ddd
#include <grp.h></grp.h>
Toshihiro Shimizu 890ddd
#include <utime.h></utime.h>
Toshihiro Shimizu 890ddd
#include <sys param.h=""></sys>
Toshihiro Shimizu 890ddd
#include <unistd.h></unistd.h>
Toshihiro Shimizu 890ddd
#include <sys types.h=""></sys>
Toshihiro Shimizu 890ddd
#include <sys timeb.h=""> // for ftime</sys>
Toshihiro Shimizu 890ddd
#include <stdio.h></stdio.h>
Toshihiro Shimizu 890ddd
#include <unistd.h></unistd.h>
Toshihiro Shimizu 890ddd
#include <dirent.h></dirent.h>
Toshihiro Shimizu 890ddd
#include <sys dir.h=""></sys>
Toshihiro Shimizu 890ddd
#include <sys param.h=""> // for getfsstat</sys>
Campbell Barton 107701
#ifdef MACOSX
Toshihiro Shimizu 890ddd
#include <sys ucred.h=""></sys>
Campbell Barton 107701
#endif
Toshihiro Shimizu 890ddd
#include <sys mount.h=""></sys>
Toshihiro Shimizu 890ddd
#include <pwd.h></pwd.h>
Toshihiro Shimizu 890ddd
#include <dlfcn.h></dlfcn.h>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TPluginManager::Plugin
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
	typedef HINSTANCE Handle;
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	typedef void *Handle;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	Handle m_handle;
Toshihiro Shimizu 890ddd
	TPluginInfo m_info;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Plugin(Handle handle)
Toshihiro Shimizu 890ddd
		: m_handle(handle)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Handle getHandle() const { return m_handle; }
Toshihiro Shimizu 890ddd
	const TPluginInfo &getInfo() const { return m_info; }
Toshihiro Shimizu 890ddd
	void setInfo(const TPluginInfo &info) { m_info = info; }
Shinya Kitaoka 3bfa54
	std::string getName() const { return m_info.getName(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef const TPluginInfo *TnzLibMainProcType();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
const char *TnzLibMainProcName = "TLibMain";
Shinya Kitaoka 9f5a1b
#if !defined(_WIN32)
Toshihiro Shimizu 890ddd
const char *TnzLibMainProcName2 = "_TLibMain";
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPluginManager::TPluginManager()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_ignoreList.insert("tnzimagevector");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPluginManager::~TPluginManager()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//   try { unloadPlugins(); } catch(...) {}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPluginManager *TPluginManager::instance()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static TPluginManager _instance;
Toshihiro Shimizu 890ddd
	return &_instance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
bool TPluginManager::isIgnored(std::string name) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_ignoreList.count(toLower(name)) > 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TPluginManager::unloadPlugins()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (PluginTable::iterator it = m_pluginTable.begin();
Toshihiro Shimizu 890ddd
		 it != m_pluginTable.end(); ++it) {
Toshihiro Shimizu 890ddd
		Plugin::Handle handle = (*it)->getHandle();
Toshihiro Shimizu 890ddd
#ifndef LINUX
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
		FreeLibrary(handle);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		dlclose(handle);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		delete (*it);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_pluginTable.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TPluginManager::loadPlugin(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if ((int)m_loadedPlugins.count(fp) > 0) {
Toshihiro Shimizu 890ddd
		TLogger::debug() << "Already loaded " << fp;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Shinya Kitaoka 3bfa54
	std::string name = fp.getName();
Toshihiro Shimizu 890ddd
	if (isIgnored(name)) {
Toshihiro Shimizu 890ddd
		TLogger::debug() << "Ignored " << fp;
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TLogger::debug() << "Loading " << fp;
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
	Plugin::Handle handle = LoadLibraryW(fp.getWideString().c_str());
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 9eb50d
	Plugin::Handle handle = dlopen(::to_string(fp).c_str(), RTLD_NOW); // RTLD_LAZY
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	if (!handle) {
Toshihiro Shimizu 890ddd
		// non riesce a caricare la libreria;
Toshihiro Shimizu 890ddd
		TLogger::warning() << "Unable to load " << fp;
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Shinya Kitaoka 3bfa54
		std::wstring getFormattedMessage(DWORD lastError);
Shinya Kitaoka 9eb50d
		TLogger::warning() << ::to_string(getFormattedMessage(GetLastError()));
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		TLogger::warning() << dlerror();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		m_loadedPlugins.insert(fp);
Toshihiro Shimizu 890ddd
		Plugin *plugin = new Plugin(handle);
Toshihiro Shimizu 890ddd
		m_pluginTable.push_back(plugin);
Toshihiro Shimizu 890ddd
		//cout << "loaded" << endl;
Toshihiro Shimizu 890ddd
		TnzLibMainProcType *tnzLibMain = 0;
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
		tnzLibMain = (TnzLibMainProcType *)
Toshihiro Shimizu 890ddd
			GetProcAddress(handle, TnzLibMainProcName);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		tnzLibMain = (TnzLibMainProcType *)
Toshihiro Shimizu 890ddd
			dlsym(handle, TnzLibMainProcName);
Toshihiro Shimizu 890ddd
		if (!tnzLibMain) //provo _ come prefisso
Toshihiro Shimizu 890ddd
			tnzLibMain = (TnzLibMainProcType *)dlsym(handle, TnzLibMainProcName2);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!tnzLibMain) {
Toshihiro Shimizu 890ddd
			// La libreria non esporta TLibMain;
Toshihiro Shimizu 890ddd
			TLogger::warning() << "Corrupted " << fp;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
			FreeLibrary(handle);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
			dlclose(handle);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			const TPluginInfo *info = tnzLibMain();
Toshihiro Shimizu 890ddd
			if (info)
Toshihiro Shimizu 890ddd
				plugin->setInfo(*info);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TPluginManager::loadPlugins(const TFilePath &dir)
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 9f5a1b
#if defined(_WIN32)
Shinya Kitaoka 3bfa54
	const std::string extension = "dll";
Toshihiro Shimizu 890ddd
#elif defined(LINUX) || defined(__sgi)
Shinya Kitaoka 3bfa54
	const std::string extension = "so";
Toshihiro Shimizu 890ddd
#elif defined(MACOSX)
Shinya Kitaoka 3bfa54
	const std::string extension = "dylib";
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePathSet dirContent = TSystem::readDirectory(dir, false);
Toshihiro Shimizu 890ddd
	if (dirContent.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (TFilePathSet::iterator it = dirContent.begin();
Toshihiro Shimizu 890ddd
		 it != dirContent.end(); it++) {
Toshihiro Shimizu 890ddd
		TFilePath fp = *it;
Toshihiro Shimizu 890ddd
		if (fp.getType() != extension)
Toshihiro Shimizu 890ddd
			continue;
Shinya Kitaoka 3bfa54
		std::wstring fullpath = fp.getWideString();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bool isDebugLibrary = (fullpath.find(L".d.") == fullpath.size() - (extension.size() + 3));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef _DEBUG
Toshihiro Shimizu 890ddd
		if (!isDebugLibrary)
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		if (isDebugLibrary)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			loadPlugin(fp);
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
			TLogger::warning() << "unexpected error loading " << fp;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TPluginManager::loadStandardPlugins()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath pluginsDir = TSystem::getDllDir() + "plugins";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//loadPlugins(pluginsDir + "io");
Toshihiro Shimizu 890ddd
	loadPlugins(pluginsDir + "fx");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
void TPluginManager::setIgnoredList(const std::set<std::string> &names)</std::string>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_ignoreList.clear();
Shinya Kitaoka 3bfa54
	for (std::set<std::string>::const_iterator it = names.begin(); it != names.end(); ++it)</std::string>
Toshihiro Shimizu 890ddd
		m_ignoreList.insert(toLower(*it));
Toshihiro Shimizu 890ddd
}