diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2015-06-07 07:24:06 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2015-06-07 08:09:31 +0200 |
commit | 71856701c8bedad3d992cb63620e695df8727812 (patch) | |
tree | fd84ea540955df1510aa0cfd24b599008ad13219 | |
parent | aa2de50523257778474c9c2ec8da8edbcb31cd8b (diff) |
plugin-support: make header-only, expose as public API
Issue: #151
Some global namespace macros are now prefixed with "OPENTRACK_" to avoid
namespace clashes.
This header is now safe to include in third-party projects.
-rw-r--r-- | facetracknoir/ui.h | 2 | ||||
-rw-r--r-- | ftnoir_tracker_hatire/ftnoir_tracker_hat.h | 2 | ||||
-rw-r--r-- | ftnoir_tracker_hatire/ftnoir_tracker_hat_dll.cpp | 2 | ||||
-rw-r--r-- | opentrack/plugin-support.cpp | 223 | ||||
-rw-r--r-- | opentrack/plugin-support.h | 50 | ||||
-rw-r--r-- | opentrack/plugin-support.hpp | 247 | ||||
-rw-r--r-- | opentrack/selected-libraries.cpp | 42 | ||||
-rw-r--r-- | opentrack/selected-libraries.hpp | 15 | ||||
-rw-r--r-- | opentrack/shortcuts.h | 2 | ||||
-rw-r--r-- | opentrack/state.hpp | 28 | ||||
-rw-r--r-- | opentrack/tracker.h | 3 | ||||
-rw-r--r-- | opentrack/work.hpp | 2 |
12 files changed, 312 insertions, 306 deletions
diff --git a/facetracknoir/ui.h b/facetracknoir/ui.h index 1705553b..f2758d81 100644 --- a/facetracknoir/ui.h +++ b/facetracknoir/ui.h @@ -48,7 +48,7 @@ #include "opentrack/options.hpp" #include "opentrack/main-settings.hpp" -#include "opentrack/plugin-support.h" +#include "opentrack/plugin-support.hpp" #include "opentrack/tracker.h" #include "opentrack/shortcuts.h" #include "opentrack/work.hpp" diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat.h b/ftnoir_tracker_hatire/ftnoir_tracker_hat.h index 020b4132..d9dd0694 100644 --- a/ftnoir_tracker_hatire/ftnoir_tracker_hat.h +++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat.h @@ -2,7 +2,7 @@ #define FTNOIR_TRACKER_HAT_H #ifdef OPENTRACK_API -# include "opentrack/plugin-support.h" +# include "opentrack/plugin-support.hpp" #else # include "..\ftnoir_tracker_base\ftnoir_tracker_base.h" #endif diff --git a/ftnoir_tracker_hatire/ftnoir_tracker_hat_dll.cpp b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dll.cpp index 5f64fe4b..66fead4f 100644 --- a/ftnoir_tracker_hatire/ftnoir_tracker_hat_dll.cpp +++ b/ftnoir_tracker_hatire/ftnoir_tracker_hat_dll.cpp @@ -91,7 +91,7 @@ QIcon TrackerDll::icon() // _GetTrackerDll@0 - Common name decoration for __stdcall functions in C language. #ifdef OPENTRACK_API -# include "opentrack/plugin-support.h" +# include "opentrack/plugin-support.hpp" extern "C" OPENTRACK_EXPORT Metadata* GetMetadata() #else # pragma comment(linker, "/export:GetTrackerDll=_GetTrackerDll@0") diff --git a/opentrack/plugin-support.cpp b/opentrack/plugin-support.cpp deleted file mode 100644 index 403798de..00000000 --- a/opentrack/plugin-support.cpp +++ /dev/null @@ -1,223 +0,0 @@ -#include <cstdio> -#include <cinttypes> -#include "plugin-support.h" -#include <QCoreApplication> -#include <QFile> -#include <QDir> - -#include <iostream> - -#ifndef _WIN32 -# include <dlfcn.h> -#endif - -SelectedLibraries::~SelectedLibraries() -{ -} - -template<typename t> -static mem<t> make_instance(mem<dylib> lib) -{ - mem<t> ret; - if (lib != nullptr && lib->Constructor) - { - qDebug() << "dylib" << (lib ? lib->filename : "<null>") << "ptr" << (intptr_t) lib->Constructor; - std::cout.flush(); - ret = mem<t>(reinterpret_cast<t*>(reinterpret_cast<CTOR_FUNPTR>(lib->Constructor)())); - } - return ret; -} - -SelectedLibraries::SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f) : - pTracker(nullptr), - pFilter(nullptr), - pProtocol(nullptr), - correct(false) -{ - pTracker = make_instance<ITracker>(t); - pProtocol = make_instance<IProtocol>(p); - pFilter = make_instance<IFilter>(f); - - if (!pTracker || !pProtocol) - { - qDebug() << "dylib load failure"; - return; - } - - if(!pProtocol->correct()) - { - qDebug() << "protocol load failure"; - return; - } - - pTracker->start_tracker(frame); - - correct = true; -} - -#if defined(__APPLE__) -# define SONAME "dylib" -#elif defined(_WIN32) -# define SONAME "dll" -#else -# define SONAME "so" -#endif - -#include <iostream> - -#ifdef _MSC_VER -# error "No support for MSVC anymore" -#else -# define LIB_PREFIX "lib" -#endif - -static bool get_metadata(mem<dylib> lib, QString& name, QIcon& icon) -{ - Metadata* meta; - if (!lib->Meta || ((meta = lib->Meta()), !meta)) - return false; - name = meta->name(); - icon = meta->icon(); - delete meta; - return true; -} - -QList<mem<dylib>> dylib::enum_libraries() -{ -#define BASE "opentrack-" -#define SUFF "-*." - const char* filters_n[] = { BASE "filter" SUFF, - BASE "tracker" SUFF, - BASE "proto" SUFF }; - const Type filters_t[] = { Filter, Tracker, Protocol }; - - QDir settingsDir( QCoreApplication::applicationDirPath() ); - - QList<mem<dylib>> ret; - - for (int i = 0; i < 3; i++) - { - QString filter = filters_n[i]; - auto t = filters_t[i]; - QStringList filenames = settingsDir.entryList(QStringList { LIB_PREFIX + filter + SONAME }, - QDir::Files, - QDir::Name); - for (int i = 0; i < filenames.size(); i++) { - QIcon icon; - QString longName; - QString str = filenames.at(i); - auto lib = std::make_shared<dylib>(str, t); - qDebug() << "Loading" << str; - std::cout.flush(); - if (!get_metadata(lib, longName, icon)) - continue; - ret.push_back(lib); - } - } - - return ret; -} - -dylib::dylib(const QString& filename, Type t) : - type(t), - filename(filename), - Dialog(nullptr), - Constructor(nullptr), - Meta(nullptr), - handle(nullptr) -{ - // otherwise dlopen opens the calling executable - if (filename.size() == 0) - return; - -#if defined(_WIN32) - QString fullPath = QCoreApplication::applicationDirPath() + "/" + this->filename; - handle = new QLibrary(fullPath); - - struct _foo { - static bool die(QLibrary*& l, bool failp) - { - if (failp) - { - qDebug() << "failed" << l->errorString(); - delete l; - l = nullptr; - } - return failp; - } - }; - - if (_foo::die(handle, !handle->load())) - return; - - Dialog = (CTOR_FUNPTR) handle->resolve("GetDialog"); - if (_foo::die(handle, !Dialog)) - return; - - Constructor = (CTOR_FUNPTR) handle->resolve("GetConstructor"); - if (_foo::die(handle, !Constructor)) - return; - - Meta = (METADATA_FUNPTR) handle->resolve("GetMetadata"); - if (_foo::die(handle, !Meta)) - return; -#else - QByteArray latin1 = QFile::encodeName(filename); - handle = dlopen(latin1.constData(), RTLD_NOW | -# if defined(__APPLE__) - RTLD_LOCAL|RTLD_FIRST|RTLD_NOW -# else - RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE -# endif - ); - - struct _foo { - static bool err(void*& handle) - { - const char* err = dlerror(); - if (err) - { - fprintf(stderr, "Error, ignoring: %s\n", err); - fflush(stderr); - dlclose(handle); - handle = nullptr; - return true; - } - return false; - } - }; - - if (handle) - { - if (_foo::err(handle)) - return; - Dialog = (CTOR_FUNPTR) dlsym(handle, "GetDialog"); - if (_foo::err(handle)) - return; - Constructor = (CTOR_FUNPTR) dlsym(handle, "GetConstructor"); - if (_foo::err(handle)) - return; - Meta = (METADATA_FUNPTR) dlsym(handle, "GetMetadata"); - if (_foo::err(handle)) - return; - } else { - (void) _foo::err(handle); - } -#endif - - auto m = mem<Metadata>(Meta()); - - icon = m->icon(); - name = m->name(); -} - -dylib::~dylib() -{ -#if defined(_WIN32) - if (handle) - delete handle; -#else - if (handle) - (void) dlclose(handle); -#endif -} diff --git a/opentrack/plugin-support.h b/opentrack/plugin-support.h deleted file mode 100644 index a2b6d403..00000000 --- a/opentrack/plugin-support.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "plugin-api.hpp" -#include "options.hpp" - -#include <QWidget> -#include <QDebug> -#include <QString> -#include <QLibrary> -#include <QFrame> -#include <QList> - - -extern "C" typedef void* (*CTOR_FUNPTR)(void); -extern "C" typedef Metadata* (*METADATA_FUNPTR)(void); - -struct dylib { - enum Type { Filter, Tracker, Protocol }; - - dylib(const QString& filename, Type t); - ~dylib(); - static QList<mem<dylib>> enum_libraries(); - - Type type; - QString filename; - - QIcon icon; - QString name; - - CTOR_FUNPTR Dialog; - CTOR_FUNPTR Constructor; - METADATA_FUNPTR Meta; -private: -#if defined(_WIN32) - QLibrary* handle; -#else - void* handle; -#endif -}; - -struct SelectedLibraries { - using dylibptr = mem<dylib>; - mem<ITracker> pTracker; - mem<IFilter> pFilter; - mem<IProtocol> pProtocol; - SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f); - SelectedLibraries() : pTracker(nullptr), pFilter(nullptr), pProtocol(nullptr), correct(false) {} - ~SelectedLibraries(); - bool correct; -}; diff --git a/opentrack/plugin-support.hpp b/opentrack/plugin-support.hpp new file mode 100644 index 00000000..bc07c106 --- /dev/null +++ b/opentrack/plugin-support.hpp @@ -0,0 +1,247 @@ +#pragma once + +/* Copyright (c) 2015 Stanislaw Halik + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include "plugin-api.hpp" +#include "options.hpp" + +#include <QWidget> +#include <QDebug> +#include <QString> +#include <QLibrary> +#include <QFrame> +#include <QList> + +#include <cstdio> +#include <cinttypes> +#include <iostream> + +#include <QCoreApplication> +#include <QFile> +#include <QDir> +#include <QList> +#include <QStringList> + +#ifndef _WIN32 +# include <dlfcn.h> +#endif + +#if defined(__APPLE__) +# define OPENTRACK_SONAME "dylib" +#elif defined(_WIN32) +# define OPENTRACK_SONAME "dll" +#else +# define OPENTRACK_SONAME "so" +#endif + +#include <iostream> + +#ifdef _MSC_VER +# error "No support for MSVC anymore" +#else +# define OPENTRACK_LIB_PREFIX "lib" +#endif + + +extern "C" typedef void* (*OPENTRACK_CTOR_FUNPTR)(void); +extern "C" typedef Metadata* (*OPENTRACK_METADATA_FUNPTR)(void); + +struct dylib { + enum Type { Filter, Tracker, Protocol }; + + dylib(const QString& filename, Type t) : + type(t), + filename(filename), + Dialog(nullptr), + Constructor(nullptr), + Meta(nullptr), + handle(nullptr) + { + // otherwise dlopen opens the calling executable + if (filename.size() == 0) + return; + +#if defined(_WIN32) + QString fullPath = QCoreApplication::applicationDirPath() + "/" + this->filename; + handle = new QLibrary(fullPath); + + struct _foo { + static bool die(QLibrary*& l, bool failp) + { + if (failp) + { + qDebug() << "failed" << l->errorString(); + delete l; + l = nullptr; + } + return failp; + } + }; + + if (_foo::die(handle, !handle->load())) + return; + + Dialog = (OPENTRACK_CTOR_FUNPTR) handle->resolve("GetDialog"); + if (_foo::die(handle, !Dialog)) + return; + + Constructor = (OPENTRACK_CTOR_FUNPTR) handle->resolve("GetConstructor"); + if (_foo::die(handle, !Constructor)) + return; + + Meta = (OPENTRACK_METADATA_FUNPTR) handle->resolve("GetMetadata"); + if (_foo::die(handle, !Meta)) + return; +#else + QByteArray latin1 = QFile::encodeName(filename); + handle = dlopen(latin1.constData(), +# if defined(__APPLE__) + RTLD_LOCAL|RTLD_FIRST|RTLD_NOW +# else + RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE +# endif + ); + + struct _foo { + static bool err(void*& handle) + { + const char* err = dlerror(); + if (err) + { + fprintf(stderr, "Error, ignoring: %s\n", err); + fflush(stderr); + dlclose(handle); + handle = nullptr; + return true; + } + return false; + } + }; + + if (handle) + { + if (_foo::err(handle)) + return; + Dialog = (OPENTRACK_CTOR_FUNPTR) dlsym(handle, "GetDialog"); + if (_foo::err(handle)) + return; + Constructor = (OPENTRACK_CTOR_FUNPTR) dlsym(handle, "GetConstructor"); + if (_foo::err(handle)) + return; + Meta = (OPENTRACK_METADATA_FUNPTR) dlsym(handle, "GetMetadata"); + if (_foo::err(handle)) + return; + } else { + (void) _foo::err(handle); + } +#endif + + auto m = mem<Metadata>(Meta()); + + icon = m->icon(); + name = m->name(); + } + ~dylib() + { +#if defined(_WIN32) + if (handle) + delete handle; +#else + if (handle) + (void) dlclose(handle); +#endif + } + + static QList<mem<dylib>> enum_libraries() + { + const char* filters_n[] = { "opentrack-filter-*.", + "opentrack-tracker-*.", + "opentrack-proto-*." + }; + const Type filters_t[] = { Filter, Tracker, Protocol }; + + QDir settingsDir( QCoreApplication::applicationDirPath() ); + + QList<mem<dylib>> ret; + + for (int i = 0; i < 3; i++) + { + QString filter = filters_n[i]; + auto t = filters_t[i]; + QStringList filenames = settingsDir.entryList(QStringList { OPENTRACK_LIB_PREFIX + filter + OPENTRACK_SONAME }, + QDir::Files, + QDir::Name); + for (int i = 0; i < filenames.size(); i++) { + QIcon icon; + QString longName; + QString str = filenames.at(i); + auto lib = std::make_shared<dylib>(str, t); + qDebug() << "Loading" << str; + std::cout.flush(); + if (!get_metadata(lib, longName, icon)) + continue; + ret.push_back(lib); + } + } + + return ret; + } + + Type type; + QString filename; + + QIcon icon; + QString name; + + OPENTRACK_CTOR_FUNPTR Dialog; + OPENTRACK_CTOR_FUNPTR Constructor; + OPENTRACK_METADATA_FUNPTR Meta; +private: +#if defined(_WIN32) + QLibrary* handle; +#else + void* handle; +#endif + + static bool get_metadata(mem<dylib> lib, QString& name, QIcon& icon) + { + Metadata* meta; + if (!lib->Meta || ((meta = lib->Meta()), !meta)) + return false; + name = meta->name(); + icon = meta->icon(); + delete meta; + return true; + } +}; + +struct Modules { + Modules() : + module_list(dylib::enum_libraries()), + filter_modules(filter(dylib::Filter)), + tracker_modules(filter(dylib::Tracker)), + protocol_modules(filter(dylib::Protocol)) + {} + QList<mem<dylib>>& filters() { return filter_modules; } + QList<mem<dylib>>& trackers() { return tracker_modules; } + QList<mem<dylib>>& protocols() { return protocol_modules; } +private: + QList<mem<dylib>> module_list; + QList<mem<dylib>> filter_modules; + QList<mem<dylib>> tracker_modules; + QList<mem<dylib>> protocol_modules; + + QList<mem<dylib>> filter(dylib::Type t) + { + QList<mem<dylib>> ret; + for (auto x : module_list) + if (x->type == t) + ret.push_back(x); + return ret; + } +}; diff --git a/opentrack/selected-libraries.cpp b/opentrack/selected-libraries.cpp new file mode 100644 index 00000000..8cb226c8 --- /dev/null +++ b/opentrack/selected-libraries.cpp @@ -0,0 +1,42 @@ +#include "opentrack/selected-libraries.hpp" +#include <QDebug> + +SelectedLibraries::~SelectedLibraries() +{ +} + +template<typename t> +static mem<t> make_instance(mem<dylib> lib) +{ + mem<t> ret; + if (lib != nullptr && lib->Constructor) + ret = mem<t>(reinterpret_cast<t*>(reinterpret_cast<OPENTRACK_CTOR_FUNPTR>(lib->Constructor)())); + return ret; +} + +SelectedLibraries::SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f) : + pTracker(nullptr), + pFilter(nullptr), + pProtocol(nullptr), + correct(false) +{ + pTracker = make_instance<ITracker>(t); + pProtocol = make_instance<IProtocol>(p); + pFilter = make_instance<IFilter>(f); + + if (!pTracker || !pProtocol) + { + qDebug() << "dylib load failure"; + return; + } + + if(!pProtocol->correct()) + { + qDebug() << "protocol load failure"; + return; + } + + pTracker->start_tracker(frame); + + correct = true; +} diff --git a/opentrack/selected-libraries.hpp b/opentrack/selected-libraries.hpp new file mode 100644 index 00000000..ffaf882c --- /dev/null +++ b/opentrack/selected-libraries.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "opentrack/plugin-support.hpp" +#include <QFrame> + +struct SelectedLibraries { + using dylibptr = mem<dylib>; + mem<ITracker> pTracker; + mem<IFilter> pFilter; + mem<IProtocol> pProtocol; + SelectedLibraries(QFrame* frame, dylibptr t, dylibptr p, dylibptr f); + SelectedLibraries() : pTracker(nullptr), pFilter(nullptr), pProtocol(nullptr), correct(false) {} + ~SelectedLibraries(); + bool correct; +}; diff --git a/opentrack/shortcuts.h b/opentrack/shortcuts.h index d0aedec0..ee0d9777 100644 --- a/opentrack/shortcuts.h +++ b/opentrack/shortcuts.h @@ -10,7 +10,7 @@ #include <QMutex> #include "qxt-mini/QxtGlobalShortcut" -#include "opentrack/plugin-support.h" +#include "opentrack/plugin-support.hpp" #include "opentrack/options.hpp" #include "opentrack/main-settings.hpp" diff --git a/opentrack/state.hpp b/opentrack/state.hpp index 2c37e5eb..a9f66241 100644 --- a/opentrack/state.hpp +++ b/opentrack/state.hpp @@ -1,36 +1,10 @@ #include <vector> #include "opentrack/options.hpp" using namespace options; -#include "opentrack/plugin-support.h" +#include "opentrack/plugin-support.hpp" #include "opentrack/main-settings.hpp" #include "opentrack/mappings.hpp" -struct Modules { - Modules() : - module_list(dylib::enum_libraries()), - filter_modules(filter(dylib::Filter)), - tracker_modules(filter(dylib::Tracker)), - protocol_modules(filter(dylib::Protocol)) - {} - QList<mem<dylib>>& filters() { return filter_modules; } - QList<mem<dylib>>& trackers() { return tracker_modules; } - QList<mem<dylib>>& protocols() { return protocol_modules; } -private: - QList<mem<dylib>> module_list; - QList<mem<dylib>> filter_modules; - QList<mem<dylib>> tracker_modules; - QList<mem<dylib>> protocol_modules; - - QList<mem<dylib>> filter(dylib::Type t) - { - QList<mem<dylib>> ret; - for (auto x : module_list) - if (x->type == t) - ret.push_back(x); - return ret; - } -}; - struct Work; struct State { diff --git a/opentrack/tracker.h b/opentrack/tracker.h index ace9fa3c..d4dc149f 100644 --- a/opentrack/tracker.h +++ b/opentrack/tracker.h @@ -3,10 +3,11 @@ #include <vector> #include "timer.hpp" -#include "plugin-support.h" +#include "plugin-support.hpp" #include "mappings.hpp" #include "pose.hpp" #include "simple-mat.hpp" +#include "selected-libraries.hpp" #include "../qfunctionconfigurator/functionconfig.h" #include "main-settings.hpp" diff --git a/opentrack/work.hpp b/opentrack/work.hpp index b93c71b6..eb5bd4ff 100644 --- a/opentrack/work.hpp +++ b/opentrack/work.hpp @@ -1,7 +1,7 @@ #pragma once #include "opentrack/main-settings.hpp" -#include "opentrack/plugin-support.h" +#include "opentrack/plugin-support.hpp" #include "opentrack/tracker.h" #include "opentrack/shortcuts.h" |