From 9040b187a1c4fa380f8a12207b9dd6d04b3a10ac Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 12 Aug 2016 18:00:49 +0200 Subject: all: rename modules s#^opentrack-##. and opentrack -> api Adjust usages. --- api/plugin-support.hpp | 216 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 api/plugin-support.hpp (limited to 'api/plugin-support.hpp') diff --git a/api/plugin-support.hpp b/api/plugin-support.hpp new file mode 100644 index 00000000..072c8da7 --- /dev/null +++ b/api/plugin-support.hpp @@ -0,0 +1,216 @@ +/* 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. + */ + +#pragma once + +#include "plugin-api.hpp" +#include "compat/options.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if defined(__APPLE__) +# define OPENTRACK_SOLIB_EXT "dylib" +#elif defined(_WIN32) +# define OPENTRACK_SOLIB_EXT "dll" +#else +# define OPENTRACK_SOLIB_EXT "so" +#endif + +#include + +#ifdef _MSC_VER +# define OPENTRACK_SOLIB_PREFIX "" +#else +# define OPENTRACK_SOLIB_PREFIX "lib" +#endif + +extern "C" typedef void* (*OPENTRACK_CTOR_FUNPTR)(void); +extern "C" typedef Metadata* (*OPENTRACK_METADATA_FUNPTR)(void); + +struct dylib final { + 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; + + handle = new QLibrary(filename); + handle->setLoadHints(QLibrary::PreventUnloadHint | handle->loadHints()); + + 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; + + auto m = mem(Meta()); + + icon = m->icon(); + name = m->name(); + } + ~dylib() + { + if (handle) + delete handle; + } + + static QList> enum_libraries(const QString& library_path) + { + const char* filters_n[] = { OPENTRACK_SOLIB_PREFIX "opentrack-filter-*." OPENTRACK_SOLIB_EXT, + OPENTRACK_SOLIB_PREFIX "opentrack-tracker-*." OPENTRACK_SOLIB_EXT, + OPENTRACK_SOLIB_PREFIX "opentrack-proto-*." OPENTRACK_SOLIB_EXT, + }; + const Type filters_t[] = { Filter, Tracker, Protocol }; + + QDir settingsDir(library_path); + + QList> ret; + + for (int i = 0; i < 3; i++) + { + QString glob = filters_n[i]; + Type t = filters_t[i]; + QStringList filenames = settingsDir.entryList(QStringList { glob }, QDir::Files, QDir::Name); + + for (const QString& filename : filenames) + { + QIcon icon; + QString longName; + auto lib = std::make_shared(library_path + filename, t); + qDebug() << "Loading" << filename; + std::cout.flush(); + if (!get_metadata(lib, longName, icon)) + continue; + using d = const mem&; + if (std::any_of(ret.cbegin(), + ret.cend(), + [&](d a) {return a->type == lib->type && a->name == lib->name;})) + { + qDebug() << "Duplicate lib" << lib->filename; + 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: + QLibrary* handle; + + static bool get_metadata(mem 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(const QString& library_path) : + module_list(dylib::enum_libraries(library_path)), + filter_modules(filter(dylib::Filter)), + tracker_modules(filter(dylib::Tracker)), + protocol_modules(filter(dylib::Protocol)) + {} + QList>& filters() { return filter_modules; } + QList>& trackers() { return tracker_modules; } + QList>& protocols() { return protocol_modules; } +private: + QList> module_list; + QList> filter_modules; + QList> tracker_modules; + QList> protocol_modules; + + template + static void sort(QList& xs) + { + std::sort(xs.begin(), xs.end(), [&](const t& a, const t& b) { return a->name.toLower() < b->name.toLower(); }); + } + + QList> filter(dylib::Type t) + { + QList> ret; + for (auto x : module_list) + if (x->type == t) + ret.push_back(x); + + sort(ret); + + return ret; + } +}; + +template +mem make_dylib_instance(mem lib) +{ + mem ret; + if (lib != nullptr && lib->Constructor) + ret = mem(reinterpret_cast(reinterpret_cast(lib->Constructor)())); + return ret; +} -- cgit v1.2.3