mirror of
https://github.com/Lurkki14/tuxclocker.git
synced 2024-11-21 15:57:25 -06:00
Implement plugin with the new lib
This commit is contained in:
parent
8eb738b9ff
commit
32b3321a33
@ -1,6 +1,8 @@
|
||||
project('tuxclocker', 'c', 'cpp')
|
||||
project('tuxclocker', 'c', 'cpp',
|
||||
default_options : ['cpp_std=c++17'])
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
cppc = meson.get_compiler('cpp')
|
||||
|
||||
incdir = include_directories('src/include', 'src/include/deps')
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# By default, library and modules (except interfaces) are built
|
||||
|
||||
option('daemon', type: 'boolean', value: 'false', description: 'Build daemon')
|
||||
option('modules', type: 'boolean', value: 'true', description: 'Build modules')
|
||||
option('plugins', type: 'boolean', value: 'true', description: 'Build plugins')
|
||||
option('interfaces', type: 'boolean', value: 'false', description: 'Build interfaces')
|
||||
option('library', type: 'boolean', value: 'true', description: 'Build library')
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
@ -7,6 +9,14 @@
|
||||
namespace TuxClocker {
|
||||
namespace Device {
|
||||
|
||||
enum class AssignmentError {
|
||||
InvalidArgument
|
||||
};
|
||||
|
||||
enum class ReadError {
|
||||
UnknownError
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Range {
|
||||
Range();
|
||||
@ -20,15 +30,43 @@ struct Enumeration {
|
||||
uint key;
|
||||
};
|
||||
|
||||
using AssignmentArgument = std::variant<int, double, uint>;
|
||||
using ReadableValue = std::variant<int, double>;
|
||||
using RangeInfo = std::variant<Range<int>, Range<double>>;
|
||||
using AssignableInfo = std::variant<RangeInfo, std::vector<Enumeration>>;
|
||||
|
||||
class Assignable {
|
||||
public:
|
||||
Assignable();
|
||||
Assignable(const std::function<std::optional<AssignmentError>(AssignmentArgument)> assignmentFunc) {
|
||||
m_assignmentFunc = assignmentFunc;
|
||||
}
|
||||
std::optional<AssignmentError> assign(AssignmentArgument arg) {
|
||||
return m_assignmentFunc(arg);
|
||||
}
|
||||
private:
|
||||
|
||||
std::function<std::optional<AssignmentError>(AssignmentArgument)> m_assignmentFunc;
|
||||
};
|
||||
|
||||
|
||||
class DynamicReadable {
|
||||
public:
|
||||
DynamicReadable(const std::function<std::variant<ReadError, ReadableValue>()> readFunc) {
|
||||
m_readFunc = readFunc;
|
||||
}
|
||||
std::variant<ReadError, ReadableValue> read() {
|
||||
return m_readFunc();
|
||||
}
|
||||
private:
|
||||
std::function<std::variant<ReadError, ReadableValue>()> m_readFunc;
|
||||
};
|
||||
|
||||
// DeviceNode has a name, and optionally implements one of [Assignable, DynamicReadable]
|
||||
using DeviceInterface = std::variant<Assignable, DynamicReadable>;
|
||||
|
||||
struct DeviceNode {
|
||||
std::string name;
|
||||
std::optional<DeviceInterface> interface;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
@ -1,9 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/dll/import.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "Device.hpp"
|
||||
#include "Tree.hpp"
|
||||
|
||||
#define TUXCLOCKER_PLUGIN_EXPORT(PluginType) \
|
||||
extern "C" BOOST_SYMBOL_EXPORT PluginType __plugin; \
|
||||
PluginType __plugin;
|
||||
|
||||
#define TUXCLOCKER_PLUGIN_SYMBOL_NAME "__plugin"
|
||||
|
||||
namespace TuxClocker {
|
||||
namespace Plugin {
|
||||
|
||||
namespace dll = boost::dll;
|
||||
|
||||
enum class InitializationError {
|
||||
UnknownError
|
||||
};
|
||||
|
||||
using namespace TuxClocker::Device;
|
||||
|
||||
class Plugin {
|
||||
public:
|
||||
static std::string pluginDirName() {return "plugins";}
|
||||
// Full path is efined at compile time
|
||||
static std::string pluginPath();
|
||||
};
|
||||
|
||||
class DevicePlugin {
|
||||
public:
|
||||
// Communicate plugin initialization success in this way since constructors cannot communicate it.
|
||||
virtual std::optional<InitializationError> initializationError() = 0;
|
||||
virtual void foo() = 0;
|
||||
virtual TreeNode<DeviceNode> deviceRootNode() = 0;
|
||||
virtual ~DevicePlugin() {}
|
||||
|
||||
// Helper for loading all DevicePlugin's
|
||||
static std::optional<std::vector<boost::shared_ptr<DevicePlugin>>> loadPlugins();
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
@ -17,9 +17,14 @@ class FlatTree {
|
||||
|
||||
template <typename T>
|
||||
class TreeNode {
|
||||
public:
|
||||
TreeNode() {};
|
||||
TreeNode(T value) {m_value = value;}
|
||||
void appendChild(T value) {m_children.push_back(TreeNode{value});}
|
||||
std::vector<TreeNode<T>> children() {return m_children;}
|
||||
private:
|
||||
T value;
|
||||
std::vector<TreeNode<T>> children;
|
||||
T m_value;
|
||||
std::vector<TreeNode<T>> m_children;
|
||||
};
|
||||
|
||||
};
|
||||
|
28
src/lib/Plugin.cpp
Normal file
28
src/lib/Plugin.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include <Plugin.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
|
||||
using namespace TuxClocker::Plugin;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::string Plugin::pluginPath() {
|
||||
return TC_PLUGIN_PATH;
|
||||
}
|
||||
|
||||
std::optional<std::vector<boost::shared_ptr<DevicePlugin>>> DevicePlugin::loadPlugins() {
|
||||
std::vector<boost::shared_ptr<DevicePlugin>> retval;
|
||||
|
||||
for (const fs::directory_entry &entry : fs::directory_iterator(Plugin::pluginPath())) {
|
||||
// Bleh, have to catch this unless I do more manual checks
|
||||
try {
|
||||
auto plugin = dll::import<DevicePlugin>(entry.path().string(), TUXCLOCKER_PLUGIN_SYMBOL_NAME);
|
||||
retval.push_back(plugin);
|
||||
}
|
||||
catch (boost::system::system_error &e) {}
|
||||
}
|
||||
|
||||
if (retval.empty()) return std::nullopt;
|
||||
return retval;
|
||||
}
|
@ -7,14 +7,14 @@
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Load an interface here
|
||||
tc_module_t *mod = tc_module_find(TC_CATEGORY_INTERFACE, "qt");
|
||||
/*tc_module_t *mod = tc_module_find(TC_CATEGORY_INTERFACE, "qt");
|
||||
|
||||
if (mod != NULL) {
|
||||
printf("successful load for %s\n", mod->name);
|
||||
mod->init_callback(argc, argv);
|
||||
|
||||
tc_module_close(mod);
|
||||
}
|
||||
}*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5,27 +5,46 @@ openssl_dep = dependency('openssl')
|
||||
# Jansson is used for module database
|
||||
jansson_dep = dependency('jansson')
|
||||
|
||||
# For posix only
|
||||
dl = cppc.find_library('dl')
|
||||
|
||||
boost_dep = dependency('boost',
|
||||
modules : ['system',
|
||||
'filesystem'])
|
||||
|
||||
libtuxclocker_posix_sources = ['lib/posix/module.c',
|
||||
'lib/posix/filesystem.c']
|
||||
|
||||
libtuxclocker_posix_libs = [cc.find_library('dl')]
|
||||
|
||||
# Compile time definition for module path
|
||||
module_path_def_template = '-DTC_MODULE_PATH="@0@/@1@/tuxclocker/modules"'
|
||||
module_path_def = module_path_def_template.format(get_option('prefix'), get_option('libdir'))
|
||||
plugin_path_def_template = '-DTC_PLUGIN_PATH="@0@/@1@/tuxclocker/plugins"'
|
||||
plugin_path_def = plugin_path_def_template.format(get_option('prefix'), get_option('libdir'))
|
||||
|
||||
libtuxclocker = shared_library('libtuxclocker',
|
||||
['lib/tc_assignable.c',
|
||||
'lib/tc_module.c',
|
||||
'lib/tc_readable.c',
|
||||
'lib/tc_common.c',
|
||||
libtuxclocker_posix_sources],
|
||||
#libtuxclocker = shared_library('libtuxclocker',
|
||||
# ['lib/tc_assignable.c',
|
||||
# 'lib/tc_module.c',
|
||||
# 'lib/tc_readable.c',
|
||||
# 'lib/tc_common.c',
|
||||
# libtuxclocker_posix_sources],
|
||||
# include_directories : incdir,
|
||||
# dependencies : [libtuxclocker_posix_libs, openssl_dep, jansson_dep],
|
||||
# c_args : module_path_def,
|
||||
# install : true)
|
||||
|
||||
libtuxclocker = shared_library('tuxclocker',
|
||||
['lib/Plugin.cpp'],
|
||||
override_options : ['cpp_std=c++17'],
|
||||
include_directories : incdir,
|
||||
dependencies : [libtuxclocker_posix_libs, openssl_dep, jansson_dep],
|
||||
c_args : module_path_def,
|
||||
dependencies : [boost_dep, dl],
|
||||
cpp_args : plugin_path_def,
|
||||
install : true)
|
||||
|
||||
subdir('modules')
|
||||
|
||||
if get_option('plugins')
|
||||
subdir('plugins')
|
||||
endif
|
||||
|
||||
subdir('main')
|
||||
|
||||
if get_option('library')
|
||||
|
@ -1 +1,34 @@
|
||||
#include <Plugin.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace TuxClocker::Plugin;
|
||||
using namespace TuxClocker::Device;
|
||||
using namespace TuxClocker;
|
||||
|
||||
class AMDPlugin : public DevicePlugin {
|
||||
public:
|
||||
AMDPlugin();
|
||||
std::optional<InitializationError> initializationError() {return std::nullopt;}
|
||||
void foo() {std::cout << "hi from AMD plugin\n";}
|
||||
TreeNode<DeviceNode> deviceRootNode();
|
||||
~AMDPlugin() {}
|
||||
private:
|
||||
TreeNode<DeviceNode> m_rootNode;
|
||||
};
|
||||
|
||||
AMDPlugin::AMDPlugin() {
|
||||
/*Assignable a([](auto arg) {
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
DeviceNode root{"AMD", a};
|
||||
m_rootNode.appendChild(root);*/
|
||||
}
|
||||
|
||||
TreeNode<DeviceNode> AMDPlugin::deviceRootNode() {
|
||||
;
|
||||
return m_rootNode;
|
||||
}
|
||||
|
||||
TUXCLOCKER_PLUGIN_EXPORT(AMDPlugin)
|
||||
|
5
src/plugins/meson.build
Normal file
5
src/plugins/meson.build
Normal file
@ -0,0 +1,5 @@
|
||||
shared_library('amd', 'AMD.cpp',
|
||||
override_options : ['cpp_std=c++17'],
|
||||
include_directories : incdir,
|
||||
install_dir : get_option('libdir') / 'tuxclocker' / 'plugins',
|
||||
install : true)
|
@ -3,136 +3,28 @@
|
||||
#include <QDBusError>
|
||||
#include <QDBusMetaType>
|
||||
#include <QDebug>
|
||||
#include <tc_module.h>
|
||||
#include <Plugin.hpp>
|
||||
|
||||
#include "AssignableAdaptorFactory.h"
|
||||
#include "EnumData.h"
|
||||
#include "Result.h"
|
||||
#include "ReadableAdaptorFactory.h"
|
||||
|
||||
void registerMetatypes() {
|
||||
//qRegisterMetaType<Result<QDBusVariant>>();
|
||||
qDBusRegisterMetaType<Result<QDBusVariant>>();
|
||||
|
||||
//qRegisterMetaType<EnumData>();
|
||||
qDBusRegisterMetaType<EnumData>();
|
||||
|
||||
qDBusRegisterMetaType<QList<EnumData>>();
|
||||
}
|
||||
|
||||
void registerReadables(QObject *parent, QDBusConnection conn) {
|
||||
uint16_t count;
|
||||
auto modules = tc_module_find_all_from_category(TC_CATEGORY_READABLE, &count);
|
||||
|
||||
QList <tc_readable_module_data_t> dataList;
|
||||
|
||||
for (uint16_t i = 0; i < count; i++) {
|
||||
auto mod = modules[i];
|
||||
/*if (modules[i]->init_callback && modules[i]->init_callback() == TC_SUCCESS) {
|
||||
auto &module = modules[i];
|
||||
// Module was initialized successfully
|
||||
// TODO : make a function in the lib to get a list of category specific data
|
||||
for (auto i = 0; i < module->category_info.num_categories; i++) {
|
||||
if (module->category_info.category_data_list[i].category == TC_READABLE) {
|
||||
dataList.append(module->category_info.category_data_list[i].readable_data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
for (uint16_t i = 0; i < mod->category_info.num_categories; i++) {
|
||||
if (mod->category_info.category_data_list[i].category == TC_READABLE
|
||||
&& mod->category_info.category_data_list[i].init
|
||||
&& mod->category_info.category_data_list[i].init() == TC_SUCCESS) {
|
||||
dataList.append(mod->category_info.category_data_list[i].readable_data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void (tc_readable_node_t*, tc_readable_module_data_t, QString, int)> traverse;
|
||||
traverse = [=, &traverse, &conn](tc_readable_node_t *node, tc_readable_module_data_t data, QString path, int n) {
|
||||
if (node->name) {
|
||||
qDebug() << node->name;
|
||||
}
|
||||
|
||||
path = path + "/" + QString::number(n);
|
||||
qDebug() << path;
|
||||
|
||||
auto obj = new QObject(parent);
|
||||
//new ReadableDynamicVariantAdaptor(obj);
|
||||
ReadableAdaptorFactory::readableAdaptor(obj, node);
|
||||
conn.registerObject(path, obj);
|
||||
|
||||
for (uint16_t i = 0; i < node->children_count; i++) {
|
||||
traverse(node->children_nodes[i], data, path, n + i);
|
||||
}
|
||||
};
|
||||
|
||||
QString p = "/Readable";
|
||||
for (auto data : dataList) {
|
||||
for (uint16_t i = 0; i < data.root_node->children_count; i++) {
|
||||
traverse(data.root_node->children_nodes[i], data, p, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void registerAssignables(QObject *parent, QDBusConnection conn) {
|
||||
uint16_t count;
|
||||
auto modules = tc_module_find_all_from_category(TC_CATEGORY_ASSIGNABLE, &count);
|
||||
|
||||
QList <tc_assignable_module_data_t> dataList;
|
||||
|
||||
for (uint16_t i = 0; i < count; i++) {
|
||||
/*if (modules[i]->init_callback && modules[i]->init_callback() == TC_SUCCESS) {
|
||||
auto &module = modules[i];
|
||||
for (uint16_t i = 0; i < module->category_info.num_categories; i++) {
|
||||
if (module->category_info.category_data_list[i].category == TC_ASSIGNABLE) {
|
||||
dataList.append(module->category_info.category_data_list[i].assignable_data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
auto mod = modules[i];
|
||||
for (uint16_t i = 0; i < mod->category_info.num_categories; i++) {
|
||||
if (mod->category_info.category_data_list[i].category == TC_ASSIGNABLE
|
||||
&& mod->category_info.category_data_list[i].init
|
||||
&& mod->category_info.category_data_list[i].init() == TC_SUCCESS) {
|
||||
dataList.append(mod->category_info.category_data_list[i].assignable_data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::function <void (tc_assignable_node_t*, tc_assignable_module_data_t, QString, int)> traverse;
|
||||
traverse = [=, &traverse, &conn](tc_assignable_node_t *node, tc_assignable_module_data_t data, QString path, int n) {
|
||||
//path = path + "/" + QString::number(n);
|
||||
|
||||
path = path + "/" + QString(node->name).replace(" ", "");
|
||||
|
||||
auto obj = new QObject(parent);
|
||||
AssignableAdaptorFactory::assignableAdaptor(obj, node);
|
||||
|
||||
if (!conn.registerObject(path, obj)) {
|
||||
qDebug() << "unable to register object";
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < node->children_count; i++) {
|
||||
traverse(node->children_nodes[i], data, path, n + i);
|
||||
}
|
||||
};
|
||||
|
||||
QString path ="/Assignable";
|
||||
for (auto data : dataList) {
|
||||
for (uint16_t i = 0; i < data.root_node->children_count; i++) {
|
||||
traverse(data.root_node->children_nodes[i], data, path, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
using namespace TuxClocker;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
registerMetatypes();
|
||||
auto plugins = Plugin::DevicePlugin::loadPlugins();
|
||||
|
||||
if (plugins.has_value()) {
|
||||
qDebug() << "found " << plugins.value().size() << " plugins";
|
||||
for (auto &plugin : plugins.value()) {
|
||||
plugin->foo();
|
||||
plugin->deviceRootNode();
|
||||
}
|
||||
}
|
||||
/*registerMetatypes();
|
||||
|
||||
QObject root;
|
||||
|
||||
@ -144,7 +36,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
if (!connection.registerService("org.tuxclocker")) {
|
||||
qDebug() << "unable to register:" << connection.lastError().message();
|
||||
}
|
||||
}*/
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
@ -2,23 +2,20 @@ qt5 = import('qt5')
|
||||
qt5_dep = dependency('qt5',
|
||||
modules : ['DBus'])
|
||||
|
||||
moc_files = qt5.preprocess(moc_headers : ['ReadableDynamicVariantAdaptor.h',
|
||||
'AssignableEnumAdaptor.h',
|
||||
'AssignableVariantRangeAdaptor.h'],
|
||||
dependencies : qt5_dep)
|
||||
boost_dep = dependency('boost', modules : ['system'])
|
||||
|
||||
#moc_files = qt5.preprocess(moc_headers : #['ReadableDynamicVariantAdaptor.h',
|
||||
# 'AssignableEnumAdaptor.h',
|
||||
# 'AssignableVariantRangeAdaptor.h'],
|
||||
# dependencies : qt5_dep)
|
||||
|
||||
sources = ['main.cpp']
|
||||
|
||||
sources = ['main.cpp',
|
||||
'AssignableAdaptorFactory.cpp',
|
||||
'AssignableEnumAdaptor.cpp',
|
||||
'AssignableVariantRangeAdaptor.cpp',
|
||||
'ReadableAdaptorFactory.cpp',
|
||||
'ReadableDynamicVariantAdaptor.cpp']
|
||||
|
||||
executable('tuxclockerd',
|
||||
moc_files,
|
||||
sources,
|
||||
override_options : ['cpp_std=c++17'],
|
||||
include_directories : incdir,
|
||||
dependencies : qt5_dep,
|
||||
dependencies : [qt5_dep, boost_dep, dl],
|
||||
link_with : libtuxclocker,
|
||||
install : true)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user