|
|
bb9720 |
/* === S Y N F I G ========================================================= */
|
|
|
bb9720 |
/*! \file synfigapp/pluginmanager.cpp
|
|
|
bb9720 |
** \brief Plugin Manager responsible for loading plugins
|
|
|
bb9720 |
**
|
|
|
bb9720 |
** $Id$
|
|
|
bb9720 |
**
|
|
|
bb9720 |
** \legal
|
|
|
705108 |
** Copyright (c) 2012-2013 Konstantin Dmitriev
|
|
|
bb9720 |
**
|
|
|
bb9720 |
** This package is free software; you can redistribute it and/or
|
|
|
bb9720 |
** modify it under the terms of the GNU General Public License as
|
|
|
bb9720 |
** published by the Free Software Foundation; either version 2 of
|
|
|
bb9720 |
** the License, or (at your option) any later version.
|
|
|
bb9720 |
**
|
|
|
bb9720 |
** This package is distributed in the hope that it will be useful,
|
|
|
bb9720 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bb9720 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bb9720 |
** General Public License for more details.
|
|
|
bb9720 |
** \endlegal
|
|
|
bb9720 |
*/
|
|
|
bb9720 |
/* ========================================================================= */
|
|
|
bb9720 |
|
|
|
bb9720 |
/* === H E A D E R S ======================================================= */
|
|
|
bb9720 |
|
|
|
bb9720 |
#ifdef USING_PCH
|
|
|
bb9720 |
# include "pch.h"
|
|
|
bb9720 |
#else
|
|
|
bb9720 |
#ifdef HAVE_CONFIG_H
|
|
|
bb9720 |
# include <config.h></config.h>
|
|
|
bb9720 |
#endif
|
|
|
bb9720 |
|
|
|
bb9720 |
#include "pluginmanager.h"
|
|
|
bb9720 |
|
|
|
bb9720 |
#include <libxml++ libxml++.h=""></libxml++>
|
|
|
bb9720 |
|
|
|
bb9720 |
#include <dirent.h></dirent.h>
|
|
|
bb9720 |
#include <sys stat.h=""></sys>
|
|
|
bb9720 |
|
|
|
bb9720 |
#include <synfig general.h=""></synfig>
|
|
|
862ccf |
#include <synfig savecanvas.h=""></synfig>
|
|
|
784691 |
#include <synfig filesystemnative.h=""></synfig>
|
|
|
862ccf |
#include <synfigapp main.h=""></synfigapp>
|
|
|
bb9720 |
|
|
|
abdbf2 |
#include <synfigapp localization.h=""></synfigapp>
|
|
bw |
94d8a6 |
|
|
|
bb9720 |
#endif
|
|
|
bb9720 |
|
|
|
bb9720 |
/* === U S I N G =========================================================== */
|
|
|
bb9720 |
|
|
|
bb9720 |
using namespace std;
|
|
|
bb9720 |
using namespace etl;
|
|
|
bb9720 |
using namespace synfig;
|
|
|
300985 |
using namespace studio;
|
|
|
bb9720 |
|
|
|
bb9720 |
/* === M A C R O S ========================================================= */
|
|
|
bb9720 |
|
|
|
862ccf |
|
|
|
bb9720 |
/* === G L O B A L S ======================================================= */
|
|
|
bb9720 |
|
|
|
bb9720 |
/* === M E T H O D S ======================================================= */
|
|
|
bb9720 |
|
|
|
bb9720 |
PluginManager::PluginManager():
|
|
|
bb9720 |
list_()
|
|
|
bb9720 |
{
|
|
|
bb9720 |
} // END of synfigapp::PluginManager::PluginManager()
|
|
|
bb9720 |
|
|
|
bb9720 |
void
|
|
|
bb9720 |
PluginManager::load_dir( const std::string &pluginsprefix )
|
|
|
bb9720 |
{
|
|
|
bb9720 |
|
|
|
bb9720 |
synfig::info("Loading plugins from %s", pluginsprefix.c_str());
|
|
|
bb9720 |
|
|
|
bb9720 |
DIR *dir;
|
|
|
bb9720 |
struct dirent *entry;
|
|
|
bb9720 |
|
|
|
bb9720 |
dir = opendir(pluginsprefix.c_str());
|
|
|
bb9720 |
if(dir) {
|
|
|
bb9720 |
while ( (entry = readdir(dir)) != NULL) {
|
|
|
bb9720 |
if ( std::string(entry->d_name) != std::string(".") && std::string(entry->d_name) != std::string("..") ) {
|
|
|
bb9720 |
std::string pluginpath;
|
|
|
bb9720 |
pluginpath = pluginsprefix+ETL_DIRECTORY_SEPARATOR+entry->d_name;
|
|
|
bb9720 |
struct stat sb;
|
|
|
b2570b |
stat(pluginpath.c_str(), &sb);
|
|
|
bb9720 |
// error handling if stat failed
|
|
|
bb9720 |
if (S_ISDIR(sb.st_mode)) {
|
|
|
bb9720 |
// checking if directory contains a plugin...
|
|
|
bb9720 |
DIR *plugindir;
|
|
|
bb9720 |
struct dirent *plugindirentry;
|
|
|
bb9720 |
|
|
|
bb9720 |
plugindir = opendir(pluginpath.c_str());
|
|
|
943360 |
if(plugindir) {
|
|
|
943360 |
while ( (plugindirentry = readdir(plugindir)) != NULL) {
|
|
|
943360 |
if ( std::string(plugindirentry->d_name) == std::string("plugin.xml") ){
|
|
|
943360 |
std::string pluginfilepath;
|
|
|
943360 |
pluginfilepath = pluginpath+ETL_DIRECTORY_SEPARATOR+plugindirentry->d_name;
|
|
|
943360 |
|
|
|
943360 |
load_plugin(pluginfilepath);
|
|
|
943360 |
}
|
|
|
943360 |
}
|
|
|
943360 |
closedir(plugindir);
|
|
|
943360 |
}
|
|
|
943360 |
else
|
|
|
943360 |
synfig::warning("Can't read plugin directory!");
|
|
|
943360 |
|
|
|
943360 |
/*plugindir = opendir(pluginpath.c_str());
|
|
|
bb9720 |
if(!plugindir) {
|
|
|
bb9720 |
synfig::warning("Can't read plugin directory!");
|
|
|
bb9720 |
return;
|
|
|
bb9720 |
}
|
|
|
bb9720 |
|
|
|
bb9720 |
while ( (plugindirentry = readdir(plugindir)) != NULL) {
|
|
|
bb9720 |
if ( std::string(plugindirentry->d_name) == std::string("plugin.xml") ){
|
|
|
bb9720 |
std::string pluginfilepath;
|
|
|
bb9720 |
pluginfilepath = pluginpath+ETL_DIRECTORY_SEPARATOR+plugindirentry->d_name;
|
|
|
bb9720 |
|
|
|
bb9720 |
load_plugin(pluginfilepath);
|
|
|
bb9720 |
}
|
|
|
943360 |
}*/
|
|
|
bb9720 |
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
|
|
|
bb9720 |
};
|
|
|
bb9720 |
|
|
|
bb9720 |
closedir(dir);
|
|
|
bb9720 |
}
|
|
|
bb9720 |
} // END of synfigapp::PluginManager::load_dir()
|
|
|
bb9720 |
|
|
|
bb9720 |
void
|
|
|
bb9720 |
PluginManager::load_plugin( const std::string &path )
|
|
|
bb9720 |
{
|
|
|
bb9720 |
// Get locale
|
|
|
bb9720 |
std::string current_locale = setlocale(LC_ALL, NULL);
|
|
|
bb9720 |
|
|
|
36b669 |
synfig::info(" Loading plugin: %s", basename(dirname(path)).c_str());
|
|
|
bb9720 |
|
|
|
bb9720 |
PluginManager::plugin p;
|
|
|
bb9720 |
std::string plugindir = dirname(path);
|
|
|
bb9720 |
p.id=plugindir;
|
|
|
bb9720 |
|
|
|
bb9720 |
// parse xml file
|
|
|
bb9720 |
try
|
|
|
bb9720 |
{
|
|
|
bb9720 |
xmlpp::DomParser parser;
|
|
|
bb9720 |
//parser.set_validate();
|
|
|
bb9720 |
parser.set_substitute_entities(); //We just want the text to be resolved/unescaped automatically.
|
|
|
bb9720 |
parser.parse_file(path);
|
|
|
bb9720 |
if(parser)
|
|
|
bb9720 |
{
|
|
|
bb9720 |
//Walk the tree:
|
|
|
bb9720 |
const xmlpp::Node* pNode = parser.get_document()->get_root_node(); //deleted by DomParser.
|
|
|
bb9720 |
if ( std::string(pNode->get_name()) == std::string("plugin") ){
|
|
|
bb9720 |
//Recurse through child nodes:
|
|
|
bb9720 |
xmlpp::Node::NodeList list = pNode->get_children();
|
|
|
bb9720 |
|
|
|
bb9720 |
unsigned int name_relevance = 0;
|
|
|
bb9720 |
|
|
|
bb9720 |
for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
|
|
|
bb9720 |
{
|
|
|
bb9720 |
const xmlpp::Node* node = *iter;
|
|
|
bb9720 |
if ( std::string(node->get_name()) == std::string("name") ) {
|
|
|
bb9720 |
|
|
|
bb9720 |
const xmlpp::Element* nodeElement = dynamic_cast<const xmlpp::element*="">(node);</const>
|
|
|
bb9720 |
|
|
|
bb9720 |
xmlpp::Node::NodeList l = nodeElement->get_children();
|
|
|
bb9720 |
xmlpp::Node::NodeList::iterator i = l.begin();
|
|
|
bb9720 |
xmlpp::Node* n = *i;
|
|
|
bb9720 |
|
|
|
bb9720 |
const xmlpp::TextNode* nodeText = dynamic_cast<const xmlpp::textnode*="">(n);</const>
|
|
|
bb9720 |
|
|
|
bb9720 |
if(nodeText)
|
|
|
bb9720 |
{
|
|
|
bb9720 |
// Get the language attribute
|
|
|
bb9720 |
const xmlpp::Attribute* langAttribute = nodeElement->get_attribute("lang", "xml");
|
|
|
bb9720 |
|
|
|
bb9720 |
if (langAttribute) {
|
|
|
bb9720 |
// Element have language attribute,
|
|
|
bb9720 |
std::string lang = langAttribute->get_value();
|
|
|
bb9720 |
// let's compare it with current locale
|
|
|
bb9720 |
if (!current_locale.compare(0, lang.size(), lang)) {
|
|
|
bb9720 |
if (lang.size() > name_relevance){
|
|
|
bb9720 |
p.name=nodeText->get_content();
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
} else {
|
|
|
bb9720 |
// Element have no language attribute - use as fallback
|
|
|
bb9720 |
if (name_relevance == 0){
|
|
|
bb9720 |
p.name=nodeText->get_content();
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
|
|
|
bb9720 |
} else if ( std::string(node->get_name()) == std::string("exec") ) {
|
|
|
bb9720 |
|
|
|
bb9720 |
xmlpp::Node::NodeList l = node->get_children();
|
|
|
bb9720 |
xmlpp::Node::NodeList::iterator i = l.begin();
|
|
|
bb9720 |
xmlpp::Node* n = *i;
|
|
|
bb9720 |
|
|
|
bb9720 |
const xmlpp::TextNode* nodeText = dynamic_cast<const xmlpp::textnode*="">(n);</const>
|
|
|
bb9720 |
|
|
|
bb9720 |
if(nodeText)
|
|
|
bb9720 |
{
|
|
|
bb9720 |
p.path=plugindir+ETL_DIRECTORY_SEPARATOR+nodeText->get_content();
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
} else {
|
|
|
bb9720 |
synfig::info("Invalid plugin.xml file.");
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
catch(const std::exception& ex)
|
|
|
bb9720 |
{
|
|
|
bb9720 |
std::cout << "Exception caught: " << ex.what() << std::endl;
|
|
|
bb9720 |
}
|
|
|
bb9720 |
|
|
|
bb9720 |
if ( p.id != "" && p.name != "" && p.path != ""){
|
|
|
bb9720 |
list_.push_back(p);
|
|
|
bb9720 |
} else {
|
|
|
bb9720 |
synfig::warning("Invalid plugin.xml file!");
|
|
|
bb9720 |
}
|
|
|
bb9720 |
}
|
|
|
bb9720 |
|
|
|
bb9720 |
PluginManager::~PluginManager()
|
|
|
bb9720 |
{
|
|
|
862ccf |
}
|