diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2019-03-28 08:31:27 +0100 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2019-03-28 08:58:40 +0100 | 
| commit | 7f156c4019165dff0f1aec4ab660f23824167e00 (patch) | |
| tree | 02fb59a0759fa157371e6922f77e4eb537d62f98 /api | |
| parent | e3e8caf61bbc22c3b278ce8bd36501b73806d524 (diff) | |
api: cleanup
- add disable warnings at module load failure
- add loading modules without looking for ctors,
  for the video module
- get rid of QList
Diffstat (limited to 'api')
| -rw-r--r-- | api/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | api/plugin-support.hpp | 219 | 
2 files changed, 119 insertions, 101 deletions
diff --git a/api/CMakeLists.txt b/api/CMakeLists.txt index 0a040a55..1454b89e 100644 --- a/api/CMakeLists.txt +++ b/api/CMakeLists.txt @@ -1,3 +1,2 @@  otr_module(api NO-COMPAT BIN) -target_link_libraries(opentrack-api opentrack-options opentrack-compat) diff --git a/api/plugin-support.hpp b/api/plugin-support.hpp index 65b8e10d..90aeb8f2 100644 --- a/api/plugin-support.hpp +++ b/api/plugin-support.hpp @@ -13,13 +13,12 @@  #include <memory>  #include <algorithm>  #include <cstring> +#include <vector>  #include <QDebug>  #include <QString>  #include <QLibrary> -#include <QList>  #include <QDir> -#include <QList>  #include <QIcon>  extern "C" { @@ -27,19 +26,26 @@ extern "C" {      using module_metadata_t = Metadata_* (*)(void);  } +enum dylib_load_mode : unsigned +{ +    dylib_load_norm  = 0, +    dylib_load_quiet = 1 << 0, +    dylib_load_none  = 1 << 1, +}; + +enum class dylib_type : unsigned +{ +    Filter    = 0xdeadbabe, +    Tracker   = 0xcafebeef, +    Protocol  = 0xdeadf00d, +    Extension = 0xcafebabe, +    Video     = 0xbadf00d, +    Invalid   = (unsigned)-1, +}; +  struct dylib final  { -    enum Type : unsigned -    { -        Filter = 0xdeadbabe, -        Tracker = 0xcafebeef, -        Protocol = 0xdeadf00d, -        Extension = 0xcafebabe, -        Video = 0xbadf00d, -        Invalid = (unsigned)-1, -    }; - -    dylib(const QString& filename_, Type t, bool load = true) : +    dylib(const QString& filename_, dylib_type t, dylib_load_mode load_mode = dylib_load_norm) :          full_filename(filename_),          module_name(trim_filename(filename_))      { @@ -55,91 +61,70 @@ struct dylib final  #   pragma clang diagnostic ignored "-Wcomma"  #endif -        if (check(!handle.load())) -            return; +        if (!handle.load()) +            goto fail; -        if (load) +        if (!(load_mode & dylib_load_none))          { -            if (check((Dialog = (module_ctor_t) handle.resolve("GetDialog"), !Dialog))) -                return; +            std::unique_ptr<Metadata_> m; -            if (check((Constructor = (module_ctor_t) handle.resolve("GetConstructor"), !Constructor))) -                return; +            if (Dialog = (module_ctor_t) handle.resolve("GetDialog"), !Dialog) +                goto fail; -            if (check((Meta = (module_metadata_t) handle.resolve("GetMetadata"), !Meta))) -                return; +            if (Constructor = (module_ctor_t) handle.resolve("GetConstructor"), !Constructor) +                goto fail; -            std::unique_ptr<Metadata_> m{Meta()}; +            if (Meta = (module_metadata_t) handle.resolve("GetMetadata"), !Meta) +                goto fail; -            if (check(!m)) -                return; +            m = std::unique_ptr<Metadata_>(Meta()); + +            if (!m) +            { +                if (!(load_mode & dylib_load_quiet)) +                { +                    qDebug() << "library" << module_name << "failed: no metadata"; +                    load_mode = dylib_load_quiet; +                } +                goto fail; +            }              icon = m->icon();              name = m->name();          }          type = t; + +        return;  #ifdef __clang__  #   pragma clang diagnostic pop  #endif -    } - -    // QLibrary refcounts the .dll's so don't forcefully unload -    ~dylib() = default; - -    static QList<std::shared_ptr<dylib>> enum_libraries(const QString& library_path) -    { -        QDir module_directory(library_path); -        QList<std::shared_ptr<dylib>> ret; - -        const struct filter_ { -            Type type{Invalid}; -            QString glob; -            bool load = true; -        } filters[] = { -            { Filter, QStringLiteral(OPENTRACK_LIBRARY_PREFIX "opentrack-filter-*." OPENTRACK_LIBRARY_EXTENSION), }, -            { Tracker, QStringLiteral(OPENTRACK_LIBRARY_PREFIX "opentrack-tracker-*." OPENTRACK_LIBRARY_EXTENSION), }, -            { Protocol, QStringLiteral(OPENTRACK_LIBRARY_PREFIX "opentrack-proto-*." OPENTRACK_LIBRARY_EXTENSION), }, -            { Extension, QStringLiteral(OPENTRACK_LIBRARY_PREFIX "opentrack-ext-*." OPENTRACK_LIBRARY_EXTENSION), }, -            { Video, QStringLiteral(OPENTRACK_LIBRARY_PREFIX "opentrack-video-*." OPENTRACK_LIBRARY_EXTENSION), false, }, -        }; -        for (const filter_& filter : filters) -        { -            for (const QString& filename : module_directory.entryList({ filter.glob }, QDir::Files, QDir::Name)) -            { -                auto lib = std::make_shared<dylib>(QStringLiteral("%1/%2").arg(library_path, filename), filter.type, filter.load); - -                if (lib->type == Invalid) -                    continue; - -                if (std::any_of(ret.cbegin(), -                                ret.cend(), -                                [&lib](const std::shared_ptr<dylib>& a) { -                                    return a->type == lib->type && a->name == lib->name; -                                })) -                { -                    qDebug() << "duplicate lib" << filename << "ident" << lib->name; -                    continue; -                } +fail: +        if (!(load_mode & dylib_load_quiet)) +            qDebug() << "library" << module_name << "failed:" << handle.errorString(); -                ret.push_back(lib); -            } -        } +        Constructor = nullptr; +        Dialog = nullptr; +        Meta = nullptr; -        return ret; +        type = dylib_type::Invalid;      } -    Type type{Invalid}; +    // QLibrary refcounts the .dll's so don't forcefully unload +    ~dylib() = default; + +    dylib_type type = dylib_type::Invalid;      QString full_filename;      QString module_name;      QIcon icon;      QString name; -    module_ctor_t Dialog{nullptr}; -    module_ctor_t Constructor{nullptr}; -    module_metadata_t Meta{nullptr}; +    module_ctor_t Dialog = nullptr; +    module_ctor_t Constructor = nullptr; +    module_metadata_t Meta = nullptr; +  private:      QLibrary handle; @@ -180,36 +165,21 @@ private:          }          return {""};      } - -    bool check(bool fail) -    { -        if (fail) -        { -            qDebug() << "library" << module_name << "failed:" << handle.errorString(); - -            Constructor = nullptr; -            Dialog = nullptr; -            Meta = nullptr; - -            type = Invalid; -        } - -        return fail; -    }  };  struct Modules final  {      using dylib_ptr = std::shared_ptr<dylib>; -    using dylib_list = QList<dylib_ptr>; - -    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)), -        extension_modules(filter(dylib::Extension)), -        video_modules(filter(dylib::Video)) +    using dylib_list = std::vector<dylib_ptr>; +    using type = dylib_type; + +    Modules(const QString& library_path, dylib_load_mode load_mode = dylib_load_norm) : +        module_list(enum_libraries(library_path, load_mode)), +        filter_modules(filter(type::Filter)), +        tracker_modules(filter(type::Tracker)), +        protocol_modules(filter(type::Protocol)), +        extension_modules(filter(type::Extension)), +        video_modules(filter(type::Video))      {}      dylib_list& filters() { return filter_modules; }      dylib_list& trackers() { return tracker_modules; } @@ -226,19 +196,68 @@ private:      static dylib_list& sorted(dylib_list& xs)      { -        std::sort(xs.begin(), xs.end(), [&](const dylib_ptr& a, const dylib_ptr& b) { return a->name.toLower() < b->name.toLower(); }); +        std::sort(xs.begin(), xs.end(), +                  [&](const dylib_ptr& a, const dylib_ptr& b) { +                      return a->name.toLower() < b->name.toLower(); +        });          return xs;      } -    dylib_list filter(dylib::Type t) +    dylib_list filter(dylib_type t)      { -        QList<std::shared_ptr<dylib>> ret; +        dylib_list ret; ret.reserve(module_list.size());          for (const auto& x : module_list)              if (x->type == t)                  ret.push_back(x);          return sorted(ret);      } + +    static dylib_list enum_libraries(const QString& library_path, +                                     dylib_load_mode load_mode = dylib_load_norm) +    { +        QDir dir(library_path); +        dylib_list ret; + +        const struct filter_ { +            type type = type::Invalid; +            QString glob; +            dylib_load_mode load_mode = dylib_load_norm; +        } filters[] = { +            { type::Filter, OPENTRACK_LIBRARY_PREFIX "opentrack-filter-*." OPENTRACK_LIBRARY_EXTENSION, }, +            { type::Tracker, OPENTRACK_LIBRARY_PREFIX "opentrack-tracker-*." OPENTRACK_LIBRARY_EXTENSION, }, +            { type::Protocol, OPENTRACK_LIBRARY_PREFIX "opentrack-proto-*." OPENTRACK_LIBRARY_EXTENSION, }, +            { type::Extension, OPENTRACK_LIBRARY_PREFIX "opentrack-ext-*." OPENTRACK_LIBRARY_EXTENSION, }, +            { type::Video, OPENTRACK_LIBRARY_PREFIX "opentrack-video-*." OPENTRACK_LIBRARY_EXTENSION, dylib_load_none, }, +        }; + +        for (const filter_& filter : filters) +        { +            for (const QString& filename : dir.entryList({ filter.glob }, QDir::Files, QDir::Name)) +            { +                dylib_load_mode load_mode_{filter.load_mode | load_mode}; +                auto lib = std::make_shared<dylib>(QString("%1/%2").arg(library_path, filename), filter.type, load_mode_); + +                if (lib->type == type::Invalid) +                    continue; + +                if (std::any_of(ret.cbegin(), +                                ret.cend(), +                                [&lib](const std::shared_ptr<dylib>& a) { +                                    return a->type == lib->type && a->name == lib->name; +                                })) +                { +                    if (!(load_mode & dylib_load_quiet)) +                        qDebug() << "duplicate lib" << filename << "ident" << lib->name; +                    continue; +                } + +                ret.push_back(std::move(lib)); +            } +        } + +        return ret; +    }  };  template<typename t>  | 
