Skip to content

File plugin.hpp

File List > illixr > plugin.hpp

Go to the documentation of this file

#pragma once

#include "phonebook.hpp"
#include "record_logger.hpp"

#include 
#include 
#include 
#ifdef __ANDROID__
#    include 
#else
#    include 
#endif
#include 
#include 
#include 
#include 

#if !defined(DOUBLE_INCLUDE) && !defined(BUILDING_MONADO_ILLIXR_DRIVER)
extern "C" {
MY_EXPORT_API bool needs_monado() {
#    ifdef MONADO_REQUIRED
    return true;
#    else
    return false;
#    endif
}
}
#endif

namespace ILLIXR {

using plugin_id_t = std::size_t;

/*
 * This gets included, but it is functionally 'private'.
 */
const record_header _plugin_start_header{
    "plugin_name",
    {
        {"plugin_id", typeid(plugin_id_t)},
        {"plugin_name", typeid(std::string)},
    },
};

class plugin {
public:
    plugin(std::string name, phonebook* pb)
        : name_{std::move(name)}
        , phonebook_{pb}
        , record_logger_{phonebook_->lookup_impl<record_logger>()}
        , id_{pb->get_next_id()} { }

    virtual ~plugin() = default;

    virtual void start() {
#ifndef __ANDROID__
        record_logger_->log(record{_plugin_start_header,
                                   {
                                       {id_},
                                       {name_},
                                   }});
#endif
    }

    virtual void stop() {
#ifndef __ANDROID__
        if (plugin_logger_)
            plugin_logger_->flush();
#endif
    }

    [[maybe_unused]] [[nodiscard]] std::string get_name() const noexcept {
        return name_;
    }

    auto spdlogger(const char* log_level) {
        if (!log_level) {
#ifdef NDEBUG
            log_level = "warn";
#else
            log_level = "debug";
#endif
        }
        std::vector<spdlog::sink_ptr> sinks;
#ifdef __ANDROID__
        auto main_sink = std::make_shared<spdlog::sinks::android_sink_mt>();
        sinks.push_back(main_sink);
#else
        auto file_sink    = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/" + name_ + ".log");
        auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
        sinks.push_back(file_sink);
        sinks.push_back(console_sink);
#endif
        if (spdlog::get(name_) == nullptr) {
            plugin_logger_ = std::make_shared<spdlog::logger>(name_, begin(sinks), end(sinks));
            plugin_logger_->set_level(spdlog::level::from_str(log_level));
            spdlog::register_logger(plugin_logger_);
        } else {
            plugin_logger_ = spdlog::get(name_);
        }
        return plugin_logger_;
    }

    [[maybe_unused]] void spd_add_file_sink(const std::string& file_name, const std::string& extension,
                                            const std::string& log_level) {
        if (!plugin_logger_) {
            throw std::runtime_error("Logger not found");
        }

        auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/" + file_name + "." + extension, true);
        file_sink->set_level(spdlog::level::from_str(log_level));
        plugin_logger_->sinks().push_back(file_sink);
        size_t sink_count = plugin_logger_->sinks().size();
        plugin_logger_->sinks()[sink_count - 1]->set_pattern("%v");
    }

protected:
    std::string                          name_;
    const phonebook*                     phonebook_;
    const std::shared_ptr<record_logger> record_logger_;
    const std::size_t                    id_;
    std::shared_ptr<spdlog::logger>      plugin_logger_;
};

#define PLUGIN_MAIN(PLUGIN_CLASS)                                         \
    extern "C" MY_EXPORT_API plugin* this_plugin_factory(phonebook* pb) { \
        auto* obj = new PLUGIN_CLASS{#PLUGIN_CLASS, pb};                  \
        return obj;                                                       \
    }

} // namespace ILLIXR