@@ -16,7 +16,7 @@ | |||
namespace rack { | |||
template <class TModule, class TModuleWidget, typename... Tags> | |||
template <class TModule, class TModuleWidget> | |||
plugin::Model* createModel(const std::string& slug) { | |||
struct TModel : plugin::Model { | |||
engine::Module* createModule() override { | |||
@@ -3,7 +3,6 @@ | |||
#include <plugin/Plugin.hpp> | |||
#include <plugin/Model.hpp> | |||
#include <vector> | |||
#include <set> | |||
namespace rack { | |||
@@ -35,14 +34,12 @@ void syncUpdates(); | |||
bool isSyncing(); | |||
Plugin* getPlugin(const std::string& pluginSlug); | |||
Model* getModel(const std::string& pluginSlug, const std::string& modelSlug); | |||
std::string normalizeTag(const std::string& tag); | |||
/** Checks that the slug contains only alphanumeric characters, "-", and "_" */ | |||
bool isSlugValid(const std::string& slug); | |||
/** Returns a string containing only the valid slug characters. */ | |||
std::string normalizeSlug(const std::string& slug); | |||
extern const std::set<std::string> allowedTags; | |||
extern std::vector<Plugin*> plugins; | |||
extern std::string loginStatus; | |||
@@ -0,0 +1,16 @@ | |||
#pragma once | |||
#include <common.hpp> | |||
#include <set> | |||
namespace rack { | |||
namespace tag { | |||
extern const std::set<std::string> allowedTags; | |||
std::string normalize(const std::string& tag); | |||
} // namespace tag | |||
} // namespace rack |
@@ -22,6 +22,7 @@ | |||
#include <string.hpp> | |||
#include <history.hpp> | |||
#include <settings.hpp> | |||
#include <tag.hpp> | |||
#include <set> | |||
#include <algorithm> | |||
@@ -377,7 +378,7 @@ struct BrowserSidebar : widget::Widget { | |||
tagList = new ui::List; | |||
tagScroll->container->addChild(tagList); | |||
for (const std::string& tag : plugin::allowedTags) { | |||
for (const std::string& tag : tag::allowedTags) { | |||
TagItem* item = new TagItem; | |||
item->text = tag; | |||
tagList->addChild(item); | |||
@@ -536,105 +536,6 @@ Model* getModel(const std::string& pluginSlug, const std::string& modelSlug) { | |||
return model; | |||
} | |||
/** List of allowed tags in human display form, alphabetized. | |||
All tags here should be in sentence caps for display consistency. | |||
However, tags are case-insensitive in plugin metadata. | |||
*/ | |||
const std::set<std::string> allowedTags = { | |||
"Arpeggiator", | |||
"Attenuator", // With a level knob and not much else. | |||
"Blank", // No parameters or ports. Serves no purpose except visual. | |||
"Chorus", | |||
"Clock generator", | |||
"Clock modulator", // Clock dividers, multipliers, etc. | |||
"Compressor", // With threshold, ratio, knee, etc parameters. | |||
"Controller", // Use only if the artist "performs" with this module. Simply having knobs is not enough. Examples: on-screen keyboard, XY pad. | |||
"Delay", | |||
"Digital", | |||
"Distortion", | |||
"Drum", | |||
"Dual", // The core functionality times two. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Dual module. | |||
"Dynamics", | |||
"Effect", | |||
"Envelope follower", | |||
"Envelope generator", | |||
"Equalizer", | |||
"Expander", // Expands the functionality of a "mother" module when placed next to it. Expanders should inherit the tags of its mother module. | |||
"External", | |||
"Flanger", | |||
"Function generator", | |||
"Granular", | |||
"LFO", | |||
"Limiter", | |||
"Logic", | |||
"Low pass gate", | |||
"MIDI", | |||
"Mixer", | |||
"Multiple", | |||
"Noise", | |||
"Panning", | |||
"Phaser", | |||
"Physical modeling", | |||
"Polyphonic", | |||
"Quad", // The core functionality times four. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Quad module. | |||
"Quantizer", | |||
"Random", | |||
"Recording", | |||
"Reverb", | |||
"Ring modulator", | |||
"Sample and hold", | |||
"Sampler", | |||
"Sequencer", | |||
"Slew limiter", | |||
"Switch", | |||
"Synth voice", // A synth voice must have, at the minimum, a built-in oscillator and envelope. | |||
"Tuner", | |||
"Utility", // Serves only extremely basic functions, like inverting, max, min, multiplying by 2, etc. | |||
"VCA", | |||
"VCF", | |||
"VCO", | |||
"Visual", | |||
"Vocoder", | |||
"Waveshaper", | |||
}; | |||
/** List of common synonyms for allowed tags. | |||
Aliases and tags must be lowercase. | |||
*/ | |||
const std::map<std::string, std::string> tagAliases = { | |||
{"amplifier", "vca"}, | |||
{"clock", "clock generator"}, | |||
{"drums", "drum"}, | |||
{"eq", "equalizer"}, | |||
{"filter", "vcf"}, | |||
{"low frequency oscillator", "lfo"}, | |||
{"lowpass gate", "low pass gate"}, | |||
{"oscillator", "vco"}, | |||
{"percussion", "drum"}, | |||
{"poly", "polyphonic"}, | |||
{"s&h", "sample and hold"}, | |||
{"voltage controlled amplifier", "vca"}, | |||
{"voltage controlled filter", "vcf"}, | |||
{"voltage controlled oscillator", "vco"}, | |||
}; | |||
std::string normalizeTag(const std::string& tag) { | |||
std::string lowercaseTag = string::lowercase(tag); | |||
// Transform aliases | |||
auto it = tagAliases.find(lowercaseTag); | |||
if (it != tagAliases.end()) | |||
lowercaseTag = it->second; | |||
// Find allowed tag | |||
for (const std::string& allowedTag : allowedTags) { | |||
if (lowercaseTag == string::lowercase(allowedTag)) | |||
return allowedTag; | |||
} | |||
return ""; | |||
} | |||
bool isSlugValid(const std::string& slug) { | |||
for (char c : slug) { | |||
if (!(std::isalnum(c) || c == '-' || c == '_')) | |||
@@ -3,6 +3,7 @@ | |||
#include <asset.hpp> | |||
#include <system.hpp> | |||
#include <string.hpp> | |||
#include <tag.hpp> | |||
namespace rack { | |||
@@ -31,7 +32,7 @@ void Model::fromJson(json_t* rootJ) { | |||
json_array_foreach(tagsJ, i, tagJ) { | |||
std::string tag = json_string_value(tagJ); | |||
// Normalize tag | |||
tag = normalizeTag(tag); | |||
tag = tag::normalize(tag); | |||
if (tag != "") | |||
tags.push_back(tag); | |||
} | |||
@@ -0,0 +1,115 @@ | |||
#include <tag.hpp> | |||
#include <string.hpp> | |||
#include <map> | |||
namespace rack { | |||
namespace tag { | |||
/** List of allowed tags in human display form, alphabetized. | |||
All tags here should be in sentence caps for display consistency. | |||
However, tags are case-insensitive in plugin metadata. | |||
*/ | |||
const std::set<std::string> allowedTags = { | |||
"Arpeggiator", | |||
"Attenuator", // With a level knob and not much else. | |||
"Blank", // No parameters or ports. Serves no purpose except visual. | |||
"Chorus", | |||
"Clock generator", | |||
"Clock modulator", // Clock dividers, multipliers, etc. | |||
"Compressor", // With threshold, ratio, knee, etc parameters. | |||
"Controller", // Use only if the artist "performs" with this module. Simply having knobs is not enough. Examples: on-screen keyboard, XY pad. | |||
"Delay", | |||
"Digital", | |||
"Distortion", | |||
"Drum", | |||
"Dual", // The core functionality times two. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Dual module. | |||
"Dynamics", | |||
"Effect", | |||
"Envelope follower", | |||
"Envelope generator", | |||
"Equalizer", | |||
"Expander", // Expands the functionality of a "mother" module when placed next to it. Expanders should inherit the tags of its mother module. | |||
"External", | |||
"Filter", | |||
"Flanger", | |||
"Function generator", | |||
"Granular", | |||
"Limiter", | |||
"Logic", | |||
"Low-frequency oscillator", | |||
"Low-pass gate", | |||
"MIDI", | |||
"Mixer", | |||
"Multiple", | |||
"Noise", | |||
"Oscillator", | |||
"Panning", | |||
"Phaser", | |||
"Physical modeling", | |||
"Polyphonic", | |||
"Quad", // The core functionality times four. If multiple channels are a requirement for the module to exist (ring modulator, mixer, etc), it is not a Quad module. | |||
"Quantizer", | |||
"Random", | |||
"Recording", | |||
"Reverb", | |||
"Ring modulator", | |||
"Sample and hold", | |||
"Sampler", | |||
"Sequencer", | |||
"Slew limiter", | |||
"Switch", | |||
"Synth voice", // A synth voice must have, at the minimum, a built-in oscillator and envelope. | |||
"Tuner", | |||
"Utility", // Serves only extremely basic functions, like inverting, max, min, multiplying by 2, etc. | |||
"Visual", | |||
"Vocoder", | |||
"Voltage-controlled amplifier", | |||
"Waveshaper", | |||
}; | |||
/** List of common synonyms for allowed tags. | |||
Aliases and tags must be lowercase. | |||
*/ | |||
const std::map<std::string, std::string> tagAliases = { | |||
{"amplifier", "voltage-controlled amplifier"}, | |||
{"clock", "clock generator"}, | |||
{"drums", "drum"}, | |||
{"eq", "equalizer"}, | |||
{"lfo", "low-frequency oscillator"}, | |||
{"low frequency oscillator", "low-frequency oscillator"}, | |||
{"low pass gate", "low-pass gate"}, | |||
{"lowpass gate", "low-pass gate"}, | |||
{"percussion", "drum"}, | |||
{"poly", "polyphonic"}, | |||
{"s&h", "sample and hold"}, | |||
{"sample & hold", "sample and hold"}, | |||
{"vca", "voltage-controlled amplifier"}, | |||
{"vcf", "filter"}, | |||
{"vco", "oscillator"}, | |||
{"voltage controlled amplifier", "voltage-controlled amplifier"}, | |||
{"voltage controlled filter", "filter"}, | |||
{"voltage controlled oscillator", "oscillator"}, | |||
}; | |||
std::string normalize(const std::string& tag) { | |||
std::string lowercaseTag = string::lowercase(tag); | |||
// Transform aliases | |||
auto it = tagAliases.find(lowercaseTag); | |||
if (it != tagAliases.end()) | |||
lowercaseTag = it->second; | |||
// Find allowed tag | |||
for (const std::string& allowedTag : allowedTags) { | |||
if (lowercaseTag == string::lowercase(allowedTag)) | |||
return allowedTag; | |||
} | |||
return ""; | |||
} | |||
} // namespace tag | |||
} // namespace rack |