27 #define OSVR_DEV_VERBOSE_DISABLE
40 #include <boost/algorithm/string/predicate.hpp>
41 #include <boost/filesystem.hpp>
42 #include <boost/noncopyable.hpp>
43 #include <boost/range/adaptor/map.hpp>
44 #include <boost/range/adaptor/reversed.hpp>
45 #include <libfunctionality/LoadPlugin.h>
52 namespace pluginhost {
53 static const auto PLUGIN_HOST_LOGGER_NAME =
"PluginHost";
55 static const auto PLUGIN_HOST_DEBUG_SUFFIX =
".debug";
57 namespace fs = boost::filesystem;
63 const std::vector<std::string> pluginPaths;
68 m_logger(util::log::make_logger(PLUGIN_HOST_LOGGER_NAME)) {}
72 for (
auto &ptr : m_regMap | boost::adaptors::map_values |
73 boost::adaptors::reversed) {
78 template <
typename MapType>
79 static inline bool isPluginLoaded(MapType
const ®Map,
80 std::string
const &pluginName) {
81 return (regMap.find(pluginName) != end(regMap));
87 libfunc::PluginHandle &plugin,
88 std::string
const &name,
90 bool shouldRethrow =
false) {
91 #if defined(_MSC_VER) && !defined(NDEBUG)
93 const std::string decoratedPluginName = name + PLUGIN_HOST_DEBUG_SUFFIX;
95 const std::string &decoratedPluginName = name;
97 log.debug() <<
"Trying to load a plugin with the name "
98 << decoratedPluginName;
100 plugin = libfunc::loadPluginByName(decoratedPluginName, ctx);
102 }
catch (std::runtime_error
const &e) {
103 log.debug() <<
"Failed: " << e.what();
113 void RegistrationContext::loadPlugin(std::string
const &pluginName) {
114 if (isPluginLoaded(m_regMap, pluginName)) {
115 throw std::runtime_error(
"Already loaded a plugin named " +
121 pluginReg->setParent(*
this);
123 bool success =
false;
124 libfunc::PluginHandle plugin;
125 auto ctx = pluginReg->extractOpaquePointer();
126 const std::string pluginPathName =
128 if (pluginPathName.empty()) {
131 success = tryLoadingPlugin(*m_logger, plugin, pluginName, ctx);
133 throw std::runtime_error(
"Could not find plugin named " +
139 const auto pluginPathNameNoExt =
140 (fs::path(pluginPathName).parent_path() /
141 fs::path(pluginPathName).stem())
145 tryLoadingPlugin(*m_logger, plugin, pluginPathName, ctx) ||
146 tryLoadingPlugin(*m_logger, plugin, pluginPathNameNoExt, ctx,
149 throw std::runtime_error(
150 "Unusual error occurred trying to load plugin named " +
154 pluginReg->takePluginHandle(plugin);
161 m_impl->pluginPaths, OSVR_PLUGIN_EXTENSION);
164 for (
const auto &plugin : pluginPathNames) {
165 m_logger->debug() <<
"Examining plugin '" << plugin <<
"'...";
166 const auto pluginBaseName =
167 fs::path(plugin).filename().stem().generic_string();
168 if (boost::iends_with(pluginBaseName, OSVR_PLUGIN_IGNORE_SUFFIX)) {
169 m_logger->debug() <<
"Ignoring manual-load plugin: "
174 #if defined(_MSC_VER)
177 const auto isDebugRuntimePlugin =
178 boost::iends_with(pluginBaseName, PLUGIN_HOST_DEBUG_SUFFIX);
180 if (isDebugRuntimePlugin) {
182 m_logger->debug() <<
"Ignoring debug-runtime plugin: "
187 if (!isDebugRuntimePlugin) {
189 m_logger->debug() <<
"Ignoring non-debug-runtime plugin: "
197 loadPlugin(pluginBaseName);
198 m_logger->debug() <<
"Successfully loaded plugin: "
200 }
catch (
const std::exception &e) {
201 m_logger->warn() <<
"Failed to load plugin " << pluginBaseName
204 m_logger->warn() <<
"Failed to load plugin " << pluginBaseName
205 <<
": Unknown error.";
213 ctx->setParent(*
this);
215 m_regMap.insert(std::make_pair(ctx->getName(), ctx));
219 for (
auto &pluginPtr : m_regMap | boost::adaptors::map_values) {
220 pluginPtr->triggerHardwareDetectCallbacks();
226 const std::string &driverName,
227 const std::string ¶ms)
const {
228 auto pluginIt = m_regMap.find(pluginName);
229 if (pluginIt == end(m_regMap)) {
230 throw std::runtime_error(
"Could not find plugin named " +
233 pluginIt->second->instantiateDriver(driverName, params);
RegistrationContext()
basic constructor
void loadPlugins()
Load all detected plugins except those with a .manualload suffix.
Header for basic internal log reference. To actually log to the produced loggers, include
~RegistrationContext()
Destructor responsible for destroying plugins in reverse order.
A data structure storing "any" by name, to reduce coupling.
Impl()
constructor - creates and caches the plugin search path
FileList getAllFilesWithExt(SearchPath const &dirPath, const std::string &ext)
Get list of files inside the directory with given extension.
void adoptPluginRegistrationContext(PluginRegPtr ctx)
Assume ownership of a plugin-specific registration context created and initialized outside of loadPlu...
util::AnyMap & data()
Access the data storage map.
SearchPath getPluginSearchPath()
Find a place where to look for plugins.
An object allowing you to log messages with a given log source name.
void triggerHardwareDetect()
Trigger any registered hardware detect callbacks.
Internal, configured header file for verbosity macros.
OSVR_EXTERN_C_BEGIN typedef void * OSVR_PluginRegContext
A context pointer passed in to your plugin's entry point and other locations of control flow transfer...
shared_ptr< PluginSpecificRegistrationContextImpl > PluginRegPtr
Pointer with ownership semantics for cleanup of plugins.
static PluginRegPtr create(std::string const &name)
Factory function that creates a plugin-specific registration context. Ownership is transferred to the...
std::string findPlugin(SearchPath const &searchPaths, const std::string &pluginName)
Given the name of a plugin, find the full path to the plugin library.
void instantiateDriver(const std::string &pluginName, const std::string &driverName, const std::string ¶ms=std::string()) const
Call a driver instantiation callback for the given plugin name and driver name.
Auto-generated configuration header - do not edit!