| @@ -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 | |||