xybrid/xybrid/config/pluginregistry.cpp

152 lines
4.8 KiB
C++
Raw Normal View History

#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;
2018-12-28 12:19:32 -05:00
// 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;
2018-12-28 12:19:32 -05:00
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;
2018-12-28 12:19:32 -05:00
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;
2018-12-28 12:19:32 -05:00
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;
2018-12-28 12:19:32 -05:00
n->init();
f(n);
});
}