aboutsummaryrefslogtreecommitdiff
path: root/util/fbcompose/PluginManager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'util/fbcompose/PluginManager.cc')
-rw-r--r--util/fbcompose/PluginManager.cc197
1 files changed, 197 insertions, 0 deletions
diff --git a/util/fbcompose/PluginManager.cc b/util/fbcompose/PluginManager.cc
new file mode 100644
index 0000000..cca1c5c
--- /dev/null
+++ b/util/fbcompose/PluginManager.cc
@@ -0,0 +1,197 @@
1/** PluginManager.cc file for the fluxbox compositor. */
2
3// Copyright (c) 2011 Gediminas Liktaras (gliktaras at gmail dot com)
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21// THE SOFTWARE.
22
23
24#ifdef HAVE_CONFIG_H
25 #include "config.h"
26#endif // HAVE_CONFIG_H
27
28#include "PluginManager.hh"
29
30#include "BasePlugin.hh"
31#include "BaseScreen.hh"
32#include "Exceptions.hh"
33#include "Logging.hh"
34#include "Utility.hh"
35
36#include <algorithm>
37#include <dlfcn.h>
38#include <sstream>
39
40using namespace FbCompositor;
41
42
43//--- CONSTRUCTORS AND DESTRUCTORS ---------------------------------------------
44
45// Costructor.
46PluginManager::PluginManager(PluginType plugin_type, const BaseScreen &screen,
47 const FbTk::FbString user_plugin_dir) :
48 m_screen(screen) {
49
50 m_plugin_type = plugin_type;
51 m_user_plugin_dir = user_plugin_dir;
52}
53
54// Destructor.
55PluginManager::~PluginManager() {
56 for (size_t i = 0; i < m_plugin_objects.size(); i++) {
57 delete m_plugin_objects[i];
58 }
59
60 std::map<FbTk::FbString, PluginLibData>::iterator it = m_plugin_libs.begin();
61 while (it != m_plugin_libs.end()) {
62 unloadPlugin(it);
63 ++it;
64 }
65}
66
67
68//--- PLUGIN MANIPULATION ------------------------------------------------------
69
70// Create a plugin object, load the appropriate library if needed.
71void PluginManager::createPluginObject(FbTk::FbString name, std::vector<FbTk::FbString> args) {
72 if (m_plugin_libs.find(name) == m_plugin_libs.end()) {
73 loadPlugin(name);
74 }
75
76 CreatePluginFunction create_function = m_plugin_libs.find(name)->second.create_function;
77 BasePlugin *new_plugin_object = (*create_function)(m_screen, args);
78 m_plugin_objects.push_back(new_plugin_object);
79}
80
81
82//--- INTERNAL PLUGIN MANIPULATION ---------------------------------------------
83
84// Load a plugin.
85void PluginManager::loadPlugin(FbTk::FbString name) {
86 static union {
87 void *void_ptr;
88 PluginTypeFunction plugin_type_func;
89 CreatePluginFunction create_plugin_func;
90 } obj_union;
91
92 std::vector<FbTk::FbString> paths = buildPluginPaths(name);
93
94 // Get the handle to the plugin so object.
95 void *handle = NULL;
96 for (size_t i = 0; i < paths.size(); i++) {
97 handle = dlopen(paths[i].c_str(), RTLD_LAZY | RTLD_LOCAL);
98 if (handle) {
99 break;
100 }
101 }
102 if (!handle) {
103 std::stringstream ss;
104 ss << "Could not find/load plugin \"" << name << "\".";
105 throw PluginException(ss.str());
106 }
107
108 // Check for the correct plugin type.
109 obj_union.void_ptr = getLibraryObject(handle, "pluginType", name.c_str(), "type function");
110 PluginTypeFunction type_func = obj_union.plugin_type_func;
111
112 if ((*(type_func))() != m_plugin_type) {
113 std::stringstream ss;
114 ss << "Plugin \"" << name << "\" is of the wrong type.";
115 throw PluginException(ss.str());
116 }
117
118 // Get the plugin creation function.
119 obj_union.void_ptr = getLibraryObject(handle, "createPlugin", name.c_str(), "creation function");
120 CreatePluginFunction create_func = obj_union.create_plugin_func;
121
122 // Track the loaded plugin.
123 PluginLibData plugin_data = { handle, create_func };
124 m_plugin_libs.insert(make_pair(name, plugin_data));
125}
126
127// Unload a plugin.
128void PluginManager::unloadPlugin(FbTk::FbString name) {
129 std::map<FbTk::FbString, PluginLibData>::iterator it = m_plugin_libs.find(name);
130
131 if (it == m_plugin_libs.end()) {
132 std::stringstream ss;
133 ss << "Plugin \"" << name << "\" is not loaded (unloadPlugin).";
134 throw PluginException(ss.str());
135 } else {
136 unloadPlugin(it);
137 }
138}
139
140// Unload a plugin (actual worker function).
141void PluginManager::unloadPlugin(std::map<FbTk::FbString, PluginLibData>::iterator it) {
142 dlclose(it->second.handle);
143
144 it->second.handle = NULL;
145 it->second.create_function = NULL;
146}
147
148
149//--- CONVENIENCE FUNCTIONS ----------------------------------------------------
150
151// Build a vector of search paths for a given plugin.
152std::vector<FbTk::FbString> PluginManager::buildPluginPaths(const FbTk::FbString &name) {
153 std::stringstream ss;
154 std::vector<FbTk::FbString> paths;
155
156 FbTk::FbString type_dir = "";
157 if (m_plugin_type == Plugin_OpenGL) {
158 type_dir = "opengl/";
159 } else if (m_plugin_type == Plugin_XRender) {
160 type_dir = "xrender/";
161 }
162
163 ss << "./plugins/" << type_dir << name << "/.libs/" << name << ".so";
164 paths.push_back(ss.str());
165 ss.str("");
166
167 ss << m_user_plugin_dir << type_dir << name << ".so";
168 paths.push_back(ss.str());
169 ss.str("");
170
171#ifdef FBCOMPOSE_PATH
172 ss << FBCOMPOSE_PATH << "/plugins/" << type_dir << name << ".so";
173 paths.push_back(ss.str());
174 ss.str("");
175#endif
176
177 paths.push_back(name);
178
179 return paths;
180}
181
182// Returns some object from the given library handle.
183void *PluginManager::getLibraryObject(void *handle, const char *object_name, const char *plugin_name,
184 const char *verbose_object_name) {
185 dlerror();
186 void *raw_object = dlsym(handle, object_name);
187 const char *error = dlerror();
188
189 if (error) {
190 dlclose(handle);
191 std::stringstream ss;
192 ss << "Error in loading " << verbose_object_name << " for \"" << plugin_name << "\" plugin: " << error;
193 throw PluginException(ss.str());
194 } else {
195 return raw_object;
196 }
197}