mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-17 03:45:56 +01:00
120 lines
3.2 KiB
C++
120 lines
3.2 KiB
C++
//
|
|
// 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()));
|
|
|
|
}
|