blob: 529d82528e766f0923b85a6007f1009828b5ed2b [file] [log] [blame]
//
// C++ Implementation: NativePresetFactory
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
extern "C" {
# include <dlfcn.h>
}
#include "NativePresetFactory.hpp"
typedef void Handle;
typedef void DestroyFunctor(Preset*);
typedef Preset * CreateFunctor(const char * url);
class LibraryPreset : public Preset {
public:
LibraryPreset(Preset * preset, DestroyFunctor * destroyFun) : Preset(preset->name(), preset->author()), _internalPreset(preset), _destroyFunctor(destroyFun) {}
inline Pipeline & pipeline() { return _internalPreset->pipeline(); }
inline virtual ~LibraryPreset() { _destroyFunctor(_internalPreset); }
inline void Render(const BeatDetect &music, const PipelineContext &context) {
return _internalPreset->Render(music, context);
}
private:
Preset * _internalPreset;
DestroyFunctor * _destroyFunctor;
};
class PresetLibrary {
public:
PresetLibrary(Handle * h, CreateFunctor * create, DestroyFunctor * destroy) :
_handle(h), _createFunctor(create), _destroyFunctor(destroy) {}
Handle * handle() { return _handle; }
CreateFunctor * createFunctor() { return _createFunctor; }
DestroyFunctor * destroyFunctor() { return _destroyFunctor; }
~PresetLibrary() {
dlclose(handle());
}
private:
Handle * _handle;
CreateFunctor * _createFunctor;
DestroyFunctor * _destroyFunctor;
};
NativePresetFactory::NativePresetFactory() {}
NativePresetFactory::~NativePresetFactory() {
for (PresetLibraryMap::iterator pos = _libraries.begin(); pos != _libraries.end(); ++pos) {
std::cerr << "deleting preset library" << std::endl;
delete(pos->second);
}
}
PresetLibrary * NativePresetFactory::loadLibrary(const std::string & url) {
if (_libraries.count(url))
return _libraries[url];
// load the preset library
void* handle = dlopen(url.c_str(), RTLD_LAZY);
if (!handle) {
std::cerr << "[NativePresetFactory] Cannot load library: " << dlerror() << '\n';
return 0;
}
// reset errors
dlerror();
// load the symbols
CreateFunctor * create = (CreateFunctor*) dlsym(handle, "create");
const char * dlsym_error = dlerror();
if (dlsym_error) {
std::cerr << "[NativePresetFactory] Cannot load symbol create: " << dlsym_error << '\n';
return 0;
}
DestroyFunctor * destroy = (DestroyFunctor*) dlsym(handle, "destroy");
dlsym_error = dlerror();
if (dlsym_error) {
std::cerr << "[NativePresetFactory] Cannot load symbol destroy: " << dlsym_error << '\n';
return 0;
}
std::cerr << "[NativePresetFactory] creating preset library from url " << url << std::endl;
PresetLibrary * library = new PresetLibrary(handle, create, destroy);
_libraries.insert(std::make_pair(url, library));
return library;
}
std::auto_ptr<Preset> NativePresetFactory::allocate
(const std::string & url, const std::string & name, const std::string & author) {
PresetLibrary * library;
if ((library = loadLibrary(url)) == 0)
return std::auto_ptr<Preset>(0);
return std::auto_ptr<Preset>(new LibraryPreset
(library->createFunctor()(url.c_str()), library->destroyFunctor()));
}