#include #include #include "plugin-support.h" #include #include #include #ifndef _WIN32 # include #endif SelectedLibraries::~SelectedLibraries() { } template static ptr make_instance(ptr lib) { ptr ret = nullptr; if (lib && lib->Constructor) ret = ptr(reinterpret_cast(reinterpret_cast(lib->Constructor)())); //qDebug() << "lib" << (lib ? lib->filename : "") << "ptr" << (intptr_t)ret.get(); return ret; } SelectedLibraries::SelectedLibraries(QFrame* frame, dylibtr t, dylibtr p, dylibtr f) : pTracker(nullptr), pFilter(nullptr), pProtocol(nullptr), correct(false) { pTracker = make_instance(t); pProtocol = make_instance(p); pFilter = make_instance(f); if (!pTracker|| !pProtocol) { qDebug() << "load failure tracker" << (intptr_t)pTracker.get() << "protocol" << (intptr_t)pProtocol.get(); return; } if (pProtocol) 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 #ifdef _MSC_VER # error "No support for MSVC anymore" #else # define LIB_PREFIX "lib" #endif static bool get_metadata(ptr 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> 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> 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(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), Dialog(nullptr), Constructor(nullptr), Meta(nullptr) { // otherwise dlopen opens the calling executable if (filename.size() == 0) return; this->filename = filename; #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 = ptr(Meta()); icon = m->icon(); name = m->name(); } dylib::~dylib() { #if defined(_WIN32) handle->unload(); #else if (handle) (void) dlclose(handle); #endif }