diff options
Diffstat (limited to 'util/fbcompose/PluginManager.cc')
-rw-r--r-- | util/fbcompose/PluginManager.cc | 197 |
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 | |||
40 | using namespace FbCompositor; | ||
41 | |||
42 | |||
43 | //--- CONSTRUCTORS AND DESTRUCTORS --------------------------------------------- | ||
44 | |||
45 | // Costructor. | ||
46 | PluginManager::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. | ||
55 | PluginManager::~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. | ||
71 | void 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. | ||
85 | void 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. | ||
128 | void 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). | ||
141 | void 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. | ||
152 | std::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. | ||
183 | void *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 | } | ||