2 Copyright (C) 2012 Intel Corporation
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "pluginloader.h"
21 #include "glibmainloop.h"
30 #include <boost/concept_check.hpp>
32 std::string get_file_contents(const char *filename)
34 std::ifstream in(filename, std::ios::in);
37 DebugOut(DebugOut::Error) << "Failed to open file '" << filename << "':' " << strerror(errno) << endl;
51 PluginLoader::PluginLoader(string configFile, int argc, char** argv): f_create(NULL), routingEngine(nullptr), mMainLoop(nullptr)
53 DebugOut()<<"Loading config file: "<<configFile<<endl;
54 std::string configBuffer = get_file_contents(configFile.c_str());
56 std::string picojsonerr = "";
58 picojson::parse(v, configBuffer.begin(), configBuffer.end(), &picojsonerr);
60 if(!picojsonerr.empty())
62 DebugOut(DebugOut::Error) << "Failed to parse main config! " << picojsonerr << endl;
63 throw std::runtime_error("Error parsing config");
66 if(v.contains("routingEngine"))
68 string restr = v.get("routingEngine").to_str();
70 routingEngine = loadRoutingEngine(restr);
74 DebugOut(DebugOut::Warning)<<"Failed to load routing engine plugin: "<<restr<<endl;
80 /// there is no mainloop entry, use default glib
81 DebugOut()<<"No routing engine specified in config. Using built-in 'core' routing engine by default."<<endl;
83 /// core wants some specific configuration settings:
84 std::map<std::string,std::string> settings;
87 for (auto q : {"lowPriorityQueueSize", "normalPriorityQueueSize", "highPriorityQueueSize"})
91 string restr = v.get(q).to_str();
96 routingEngine = new Core(settings);
100 if(v.contains("plugins"))
102 std::string pluginsPath = v.get("plugins").to_str();
103 scanPluginDir(pluginsPath);
106 if(v.contains("mainloop"))
108 /// there is a mainloop entry. Load the plugin:
110 string mainloopstr = v.get("mainloop").to_str();
112 mMainLoop = loadMainLoop(mainloopstr, argc, argv);
116 DebugOut(DebugOut::Warning)<<"Failed to load main loop plugin."<<endl;
121 /// there is no mainloop entry, use default glib
122 DebugOut()<<"No mainloop specified in config. Using glib by default."<<endl;
123 mMainLoop = new GlibMainLoop(argc, argv);
127 for (auto q : {"sources", "sinks"})
129 if(v.contains("sources"))
131 picojson::array list = v.get(q).get<picojson::array>();
134 DebugOut() << "Error getting list for " << q << endl;
139 std::map<std::string, std::string> configurationMap;
140 for( auto obj : src.get<picojson::object>())
142 string valstr = obj.second.to_str();
143 string key = obj.first;
145 DebugOut() << "plugin config key: " << key << "value:" << valstr << endl;
147 configurationMap[key] = valstr;
150 string path = configurationMap["path"];
152 if(!loadPlugin(path, configurationMap))
153 DebugOut(DebugOut::Warning) << "Failed to load plugin: " << path <<endl;
159 Core* core = static_cast<Core*>(routingEngine);
160 if( core != nullptr )
162 core->inspectSupported();
166 PluginLoader::~PluginLoader()
168 for(auto handle : openHandles)
172 IMainLoop *PluginLoader::mainloop()
177 std::string PluginLoader::errorString()
182 void PluginLoader::scanPluginDir(const std::string & dir)
184 DebugOut() << "Scanning plugin directory: " << dir << endl;
186 auto pluginsDirectory = amb::make_gobject(g_file_new_for_path(dir.c_str()));
188 GError* enumerateError = nullptr;
190 auto enumerator = amb::make_gobject(g_file_enumerate_children(pluginsDirectory.get(), G_FILE_ATTRIBUTE_ID_FILE,
191 G_FILE_QUERY_INFO_NONE, nullptr,
193 auto enumerateErrorPtr = amb::make_super(enumerateError);
195 if(enumerateErrorPtr)
197 DebugOut(DebugOut::Error) << "Scanning plugin directory: " << enumerateErrorPtr->message << endl;
201 GError* errorGetFile = nullptr;
202 while(auto pluginConfig = amb::make_gobject(g_file_enumerator_next_file(enumerator.get(), nullptr, &errorGetFile)))
204 std::string name = g_file_info_get_name(pluginConfig.get());
206 DebugOut() << "Found file: " << name << endl;
207 std::string fullpath = dir + (boost::algorithm::ends_with(dir, "/") ? "":"/") + name;
208 std::string data = get_file_contents(fullpath.c_str());
210 DebugOut() << "data: " << data << endl;
212 if(!readPluginConfig(data))
214 DebugOut(DebugOut::Error) << "Reading contentds of file: " << name << endl;
218 auto errorGetFilePtr = amb::make_super(errorGetFile);
222 DebugOut(DebugOut::Error) << "enumerating file: " << errorGetFilePtr->message << endl;
227 bool PluginLoader::readPluginConfig(const string &configData)
232 picojson::parse(v, configData.begin(), configData.end(), &err);
236 DebugOut(DebugOut::Error) << err << endl;
240 std::string pluginName;
241 if(v.contains("name"))
243 pluginName = v.get("name").to_str();
246 std::string pluginPath;
247 if(v.contains("path"))
249 pluginPath = v.get("path").to_str();
253 DebugOut(DebugOut::Error) << "config missing 'path'." << endl;
257 bool enabled = false;
258 if(v.contains("enabled"))
260 enabled = v.get("enabled").get<bool>();
264 DebugOut(DebugOut::Error) << "config missing 'enabled'." << endl;
268 DebugOut() << "Plugin: " << pluginName << endl;
269 DebugOut() << "Path: " << pluginPath << endl;
270 DebugOut() << "Enabled: " << enabled << endl;
274 std::map<std::string, std::string> otherConfig;
276 picojson::object obj = v.get<picojson::object>();
279 if(!itr.second.is<std::string>())
280 otherConfig[itr.first] = itr.second.serialize();
282 otherConfig[itr.first] = itr.second.to_str();
285 loadPlugin(pluginPath, otherConfig);