2
* Copyright © 2005 Novell, Inc.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Novell, Inc. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Novell, Inc. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
26
#include "core/plugin.h"
27
#include "privatescreen.h"
29
#include <boost/scoped_array.hpp>
30
#include <boost/foreach.hpp>
39
#include <sys/types.h>
44
#define foreach BOOST_FOREACH
47
CompPlugin::Map pluginsMap;
48
CompPlugin::List plugins;
50
class CorePluginVTable : public CompPlugin::VTable
56
CompOption::Vector & getOptions ();
58
bool setOption (const CompString &name,
59
CompOption::Value &value);
62
COMPIZ_PLUGIN_20090315 (core, CorePluginVTable)
64
CompPlugin::VTable * getCoreVTable ()
68
return getCompPluginVTable20090315_core ();
75
CorePluginVTable::init ()
81
CorePluginVTable::getOptions ()
83
return screen->getOptions ();
87
CorePluginVTable::setOption (const CompString &name,
88
CompOption::Value &value)
90
return screen->setOption (name, value);
94
cloaderLoadPlugin (CompPlugin *p,
101
if (strcmp (name, getCoreVTable ()->name ().c_str ()))
104
p->vTable = getCoreVTable ();
105
p->devPrivate.ptr = NULL;
106
p->devType = "cloader";
112
cloaderUnloadPlugin (CompPlugin *p)
117
static CompStringList
118
cloaderListPlugins (const char *path)
123
return CompStringList ();
125
rv.push_back (CompString (getCoreVTable ()->name ()));
131
dlloaderLoadPlugin (CompPlugin *p,
138
struct stat fileInfo;
140
if (cloaderLoadPlugin (p, path, name))
153
if (stat (file.c_str (), &fileInfo) != 0)
155
/* file likely not present */
156
compLogMessage ("core", CompLogLevelDebug,
157
"Could not stat() file %s : %s",
158
file.c_str (), strerror (errno));
162
int open_flags = RTLD_LAZY;
164
// Do not unload the library during dlclose.
165
open_flags |= RTLD_NODELETE;
166
// Make the symbols available globally
167
open_flags |= RTLD_GLOBAL;
169
dlhand = dlopen (file.c_str (), open_flags);
172
PluginGetInfoProc getInfo;
178
snprintf (sym, 1024, "getCompPluginVTable20090315_%s", name);
179
getInfo = (PluginGetInfoProc) dlsym (dlhand, sym);
184
compLogMessage ("core", CompLogLevelError, "dlsym: %s", error);
190
p->vTable = (*getInfo) ();
193
compLogMessage ("core", CompLogLevelError,
194
"Couldn't get vtable from '%s' plugin",
199
p->devPrivate.ptr = dlhand;
200
p->devType = "dlloader";
207
compLogMessage ("core", CompLogLevelError,
208
"Couldn't load plugin '%s' : %s",
209
file.c_str (), dlerror ());
212
if (!loaded && dlhand)
219
dlloaderUnloadPlugin (CompPlugin *p)
221
if (p->devType == "dlloader")
224
dlclose (p->devPrivate.ptr);
227
cloaderUnloadPlugin (p);
231
dlloaderFilter (const struct dirent *name)
233
int length = strlen (name->d_name);
238
if (strncmp (name->d_name, "lib", 3) ||
239
strncmp (name->d_name + length - 3, ".so", 3))
245
static CompStringList
246
dlloaderListPlugins (const char *path)
248
struct dirent **nameList;
250
int length, nFile, i;
252
CompStringList rv = cloaderListPlugins (path);
257
nFile = scandir (path, &nameList, dlloaderFilter, alphasort);
261
for (i = 0; i < nFile; i++)
263
length = strlen (nameList[i]->d_name);
265
strncpy (name, nameList[i]->d_name + 3, length - 6);
266
name[length - 6] = '\0';
268
rv.push_back (CompString (name));
274
LoadPluginProc loaderLoadPlugin = dlloaderLoadPlugin;
275
UnloadPluginProc loaderUnloadPlugin = dlloaderUnloadPlugin;
276
ListPluginsProc loaderListPlugins = dlloaderListPlugins;
280
CompManager::initPlugin (CompPlugin *p)
283
if (!p->vTable->init ())
285
compLogMessage ("core", CompLogLevelError,
286
"InitPlugin '%s' failed", p->vTable->name ().c_str ());
290
if (screen && screen->priv->initialized)
292
if (!p->vTable->initScreen (screen))
294
compLogMessage (p->vTable->name ().c_str (), CompLogLevelError,
295
"initScreen failed");
299
if (!screen->initPluginForScreen (p))
310
CompManager::finiPlugin (CompPlugin *p)
315
screen->finiPluginForScreen (p);
316
p->vTable->finiScreen (screen);
323
CompScreen::initPluginForScreen (CompPlugin *p)
325
WRAPABLE_HND_FUNCTN_RETURN (bool, initPluginForScreen, p)
326
return _initPluginForScreen (p);
330
CompScreenImpl::_initPluginForScreen (CompPlugin *p)
333
CompWindowList::iterator it, fail;
336
it = fail = priv->windows.begin ();
337
for (;it != priv->windows.end (); it++)
340
if (!p->vTable->initWindow (w))
342
compLogMessage (p->vTable->name ().c_str (), CompLogLevelError,
343
"initWindow failed");
349
it = priv->windows.begin ();
350
for (;it != fail; it++)
353
p->vTable->finiWindow (w);
360
CompScreen::finiPluginForScreen (CompPlugin *p)
362
WRAPABLE_HND_FUNCTN (finiPluginForScreen, p)
363
_finiPluginForScreen (p);
367
CompScreenImpl::_finiPluginForScreen (CompPlugin *p)
369
foreach (CompWindow *w, priv->windows)
370
p->vTable->finiWindow (w);
374
CompPlugin::screenInitPlugins (CompScreen *s)
376
CompPlugin::List::reverse_iterator it = plugins.rbegin ();
378
CompPlugin *p = NULL;
380
/* Plugins is a btf list, so iterate it in reverse */
381
while (it != plugins.rend ())
385
if (p->vTable->initScreen (s))
386
s->initPluginForScreen (p);
395
CompPlugin::screenFiniPlugins (CompScreen *s)
397
foreach (CompPlugin *p, plugins)
399
s->finiPluginForScreen (p);
400
p->vTable->finiScreen (s);
406
CompPlugin::windowInitPlugins (CompWindow *w)
410
for (List::reverse_iterator rit = plugins.rbegin ();
411
rit != plugins.rend (); ++rit)
413
status &= (*rit)->vTable->initWindow (w);
420
CompPlugin::windowFiniPlugins (CompWindow *w)
422
foreach (CompPlugin *p, plugins)
424
p->vTable->finiWindow (w);
430
CompPlugin::find (const char *name)
432
CompPlugin::Map::iterator it = pluginsMap.find (name);
434
if (it != pluginsMap.end ())
441
CompPlugin::unload (CompPlugin *p)
443
loaderUnloadPlugin (p);
448
CompPlugin::load (const char *name)
450
std::auto_ptr<CompPlugin>p(new CompPlugin ());
452
p->devPrivate.uval = 0;
457
if (char* home = getenv ("HOME"))
459
boost::scoped_array<char> plugindir(new char [strlen (home) + strlen (HOME_PLUGINDIR) + 3]);
460
sprintf (plugindir.get(), "%s/%s", home, HOME_PLUGINDIR);
462
if (loaderLoadPlugin (p.get(), plugindir.get(), name))
466
if (loaderLoadPlugin (p.get(), PLUGINDIR, name))
469
if (loaderLoadPlugin (p.get(), NULL, name))
472
compLogMessage ("core", CompLogLevelError,
473
"Couldn't load plugin '%s'", name);
479
CompPlugin::push (CompPlugin *p)
481
const char *name = p->vTable->name ().c_str ();
483
std::pair<CompPlugin::Map::iterator, bool> insertRet =
484
pluginsMap.insert (std::pair<const char *, CompPlugin *> (name, p));
486
if (!insertRet.second)
488
compLogMessage ("core", CompLogLevelWarn,
489
"Plugin '%s' already active",
490
p->vTable->name ().c_str ());
495
plugins.push_front (p);
497
if (!CompManager::initPlugin (p))
499
compLogMessage ("core", CompLogLevelError,
500
"Couldn't activate plugin '%s'", name);
502
pluginsMap.erase (name);
503
plugins.pop_front ();
512
CompPlugin::pop (void)
514
if (plugins.empty ())
517
CompPlugin *p = plugins.front ();
522
pluginsMap.erase (p->vTable->name ().c_str ());
524
CompManager::finiPlugin (p);
526
plugins.pop_front ();
532
CompPlugin::getPlugins (void)
538
CompPlugin::availablePlugins ()
540
CompStringList homeList;
542
if (char* home = getenv ("HOME"))
544
boost::scoped_array<char> plugindir(new char [strlen (home) + strlen (HOME_PLUGINDIR) + 3]);
545
sprintf (plugindir.get(), "%s/%s", home, HOME_PLUGINDIR);
547
homeList = loaderListPlugins (plugindir.get());
550
std::set<CompString> set;
552
CompStringList pluginList = loaderListPlugins (PLUGINDIR);
553
CompStringList currentList = loaderListPlugins (0);
555
std::copy(homeList.begin(), homeList.end(), std::inserter(set, set.end()));
556
std::copy(pluginList.begin(), pluginList.end(), std::inserter(set, set.end()));
557
std::copy(currentList.begin(), currentList.end(), std::inserter(set, set.end()));
559
return CompStringList(set.begin(), set.end());
563
CompPlugin::getPluginABI (const char *name)
565
CompPlugin *p = find (name);
573
if (!screen->hasValue (s))
576
return screen->getValue (s).uval;
580
CompPlugin::checkPluginABI (const char *name,
585
pluginABI = getPluginABI (name);
588
compLogMessage ("core", CompLogLevelError,
589
"Plugin '%s' not loaded.\n", name);
592
else if (pluginABI != abi)
594
compLogMessage ("core", CompLogLevelError,
595
"Plugin '%s' has ABI version '%d', expected "
596
"ABI version '%d'.\n",
597
name, pluginABI, abi);
604
CompPlugin::VTable::VTable () :
610
CompPlugin::VTable::~VTable ()
617
CompPlugin::VTable::initVTable (CompString name,
618
CompPlugin::VTable **self)
629
CompPlugin::VTable::name () const
635
CompPlugin::VTable::fini ()
640
CompPlugin::VTable::initScreen (CompScreen *)
646
CompPlugin::VTable::finiScreen (CompScreen *)
651
CompPlugin::VTable::initWindow (CompWindow *)
657
CompPlugin::VTable::finiWindow (CompWindow *)
662
CompPlugin::VTable::getOptions ()
668
CompPlugin::VTable::setOption (const CompString &name,
669
CompOption::Value &value)