xybrid/xybrid/config/pluginregistry.cpp

152 lines
4.8 KiB
C++
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#include "pluginregistry.h"
using namespace Xybrid::Config;
#include <list>
#include <map>
#include <unordered_map>
#include <QMenu>
#include "data/graph.h"
using namespace Xybrid::Data;
#include "gadgets/ioport.h"
using Xybrid::Gadgets::IOPort;
#include "util/strings.h"
namespace {
typedef std::list<std::function<void()>> fqueue; // typedef so QtCreator's auto indent doesn't completely break :|
fqueue& regQueue() {
static fqueue q;
return q;
}
bool& initialized() { static bool b = false; return b; }
std::unordered_map<std::string, std::shared_ptr<PluginInfo>> plugins;
std::string priorityCategories[] {
"Gadget", "Instrument", "Effect"
};
}
bool PluginRegistry::enqueueRegistration(std::function<void ()> f) {
auto& queue = regQueue();
queue.push_back(f);
if (initialized()) f();
return true;
}
void PluginRegistry::init() {
if (initialized()) return;
for (auto& f : regQueue()) f();
initialized() = true;
}
void PluginRegistry::registerPlugin(std::shared_ptr<PluginInfo> pi) {
if (pi->id.empty()) return;
if (plugins.find(pi->id) != plugins.end()) return;
plugins[pi->id] = pi;
// there might be a better way to do this?
for (auto& id : pi->oldIds) plugins[id] = pi;
}
std::shared_ptr<Node> PluginRegistry::createInstance(const std::string& id) {
auto f = plugins.find(id);
if (f == plugins.end()) return nullptr;
auto n = f->second->createInstance();
n->plugin = f->second;
n->init();
return n;
}
void PluginRegistry::populatePluginMenu(QMenu* m, std::function<void (std::shared_ptr<Node>)> f, Graph* g) {
std::map<std::string, std::map<std::string, std::shared_ptr<PluginInfo>>> cm; // category map
cm.try_emplace(""); // force empty category
for (auto& i : plugins) {
if (i.second->hidden) continue;
cm.try_emplace(i.second->category);
cm[i.second->category][i.second->displayName] = i.second;
}
// I/O ports
if (g) {
auto* mio = m->addMenu("I/O Port");
//auto* mi = mio->addMenu("Input");
//auto* mo = mio->addMenu("Output");
Port::DataType d[] {Port::Audio, Port::Command};
for (auto dt : d) {
auto* mi = mio->addMenu(QString("&%1 In").arg(Util::enumName(dt)));
auto* mo = mio->addMenu(QString("&%1 Out").arg(Util::enumName(dt)));
//mi->setStyleSheet("QMenu { menu-scrollable: 1; }");
//mi->setFixedHeight(256);
for (int ih = 0; ih < 16; ih++) {
QString n = QString::number(ih, 16).toUpper();
auto* mis = mi->addMenu(QString(u8"%10-%1F").arg(n));
auto* mos = mo->addMenu(QString(u8"%10-%1F").arg(n));
for (int il = 0; il < 16; il++) {
int i = ih*16+il;
QString nn = Util::hex(i);
mis->addAction(nn, [f, dt, i] {
auto n = std::static_pointer_cast<IOPort>(createInstance("ioport"));
n->setPort(Port::Input, dt, static_cast<uint8_t>(i));
f(n);
})->setEnabled(!g->port(Port::Input, dt, static_cast<uint8_t>(i)));
mos->addAction(nn, [f, dt, i] {
auto n = std::static_pointer_cast<IOPort>(createInstance("ioport"));
n->setPort(Port::Output, dt, static_cast<uint8_t>(i));
f(n);
})->setEnabled(!g->port(Port::Output, dt, static_cast<uint8_t>(i)));
}
}
//
}
m->addSeparator();
}
// populate priorities into menu
for (auto& pc : priorityCategories) {
if (auto c = cm.find(pc); c != cm.end()) {
auto* ccm = m->addMenu(QString::fromStdString(c->first));
for (auto& i : c->second) {
ccm->addAction(QString::fromStdString(i.second->displayName), [f, pi = i.second] {
auto n = pi->createInstance();
n->plugin = pi;
n->init();
f(n);
});
}
cm.erase(pc);
}
}
// then any other category
for (auto& c : cm) {
if (c.first.empty() || c.second.empty()) continue;
auto* ccm = m->addMenu(QString::fromStdString(c.first));
for (auto& i : c.second) {
ccm->addAction(QString::fromStdString(i.second->displayName), [f, pi = i.second] {
auto n = pi->createInstance();
n->plugin = pi;
n->init();
f(n);
});
}
}
m->addSeparator();
for (auto& i : cm[""]) m->addAction(QString::fromStdString(i.second->displayName), [f, pi = i.second] {
auto n = pi->createInstance();
n->plugin = pi;
n->init();
f(n);
});
}