slug for patches instead of manufacturerSlugtags/v0.5.0
@@ -66,19 +66,19 @@ struct Plugin { | |||
/** OS-dependent library handle */ | |||
void *handle = NULL; | |||
/** Used when syncing plugins with the API */ | |||
/** Must be unique. Used for patch files and the VCV store API. | |||
To guarantee uniqueness, it is a good idea to prefix the slug by your "company name" if available, e.g. "MyCompany-MyPlugin" | |||
*/ | |||
std::string slug; | |||
// Optional plugin metadata | |||
/** The version of your plugin | |||
/** The version of your plugin (optional) | |||
Plugins should follow the versioning scheme described at https://github.com/VCVRack/Rack/issues/266 | |||
Do not include the "v" in "v1.0" for example. | |||
*/ | |||
std::string version; | |||
/** URL for plugin homepage */ | |||
/** URL for plugin homepage (optional) */ | |||
std::string website; | |||
/** URL for plugin manual */ | |||
/** URL for plugin manual (optional) */ | |||
std::string manual; | |||
virtual ~Plugin(); | |||
@@ -91,11 +91,12 @@ struct Model { | |||
std::string slug; | |||
/** Human readable name for your model, e.g. "Voltage Controlled Oscillator" */ | |||
std::string name; | |||
/** An identifier for the manufacturer, e.g. "foo". Used for saving patches. */ | |||
std::string manufacturerSlug; | |||
/** Human readable name for the manufacturer, e.g. "Foo Modular" */ | |||
std::string manufacturerName; | |||
/** List of tags representing the function(s) of the module */ | |||
/** The name of the manufacturer group of the module. | |||
This might be different than the plugin slug. For example, if you create multiple plugins but want them to be branded similarly, you may use the same manufacturer name in multiple plugins. | |||
You may even have multiple manufacturers in one plugin, although this would be unusual. | |||
*/ | |||
std::string manufacturer; | |||
/** List of tags representing the function(s) of the module (optional) */ | |||
std::list<ModelTag> tags; | |||
virtual ~Model() {} | |||
@@ -19,7 +19,7 @@ namespace rack { | |||
template <class TModuleWidget, typename... Tags> | |||
Model *createModel(std::string manufacturerSlug, std::string manufacturerName, std::string slug, std::string name, Tags... tags) { | |||
Model *createModel(std::string manufacturer, std::string slug, std::string name, Tags... tags) { | |||
struct TModel : Model { | |||
ModuleWidget *createModuleWidget() override { | |||
ModuleWidget *moduleWidget = new TModuleWidget(); | |||
@@ -28,10 +28,9 @@ Model *createModel(std::string manufacturerSlug, std::string manufacturerName, s | |||
} | |||
}; | |||
Model *model = new TModel(); | |||
model->manufacturer = manufacturer; | |||
model->slug = slug; | |||
model->name = name; | |||
model->manufacturerSlug = manufacturerSlug; | |||
model->manufacturerName = manufacturerName; | |||
model->tags = {tags...}; | |||
return model; | |||
} | |||
@@ -61,7 +61,7 @@ json_t *ModuleWidget::toJson() { | |||
json_t *rootJ = json_object(); | |||
// manufacturer | |||
json_object_set_new(rootJ, "manufacturer", json_string(model->manufacturerSlug.c_str())); | |||
json_object_set_new(rootJ, "plugin", json_string(model->plugin->slug.c_str())); | |||
// model | |||
json_object_set_new(rootJ, "model", json_string(model->slug.c_str())); | |||
// pos | |||
@@ -278,7 +278,7 @@ Menu *ModuleWidget::createContextMenu() { | |||
Menu *menu = gScene->createMenu(); | |||
MenuLabel *menuLabel = new MenuLabel(); | |||
menuLabel->text = model->manufacturerName + " " + model->name; | |||
menuLabel->text = model->manufacturer + " " + model->name; | |||
menu->pushChild(menuLabel); | |||
ResetMenuItem *resetItem = new ResetMenuItem(); | |||
@@ -204,29 +204,38 @@ void RackWidget::fromJson(json_t *rootJ) { | |||
size_t moduleId; | |||
json_t *moduleJ; | |||
json_array_foreach(modulesJ, moduleId, moduleJ) { | |||
json_t *manufacturerSlugJ = json_object_get(moduleJ, "manufacturer"); | |||
if (!manufacturerSlugJ) { | |||
// Backward compatibility with Rack v0.4 and lower | |||
manufacturerSlugJ = json_object_get(moduleJ, "plugin"); | |||
if (!manufacturerSlugJ) continue; | |||
} | |||
json_t *pluginSlugJ = json_object_get(moduleJ, "plugin"); | |||
if (!pluginSlugJ) continue; | |||
json_t *modelSlugJ = json_object_get(moduleJ, "model"); | |||
if (!modelSlugJ) continue; | |||
std::string manufacturerSlug = json_string_value(manufacturerSlugJ); | |||
std::string pluginSlug = json_string_value(pluginSlugJ); | |||
std::string modelSlug = json_string_value(modelSlugJ); | |||
// Search for plugin | |||
Plugin *plugin = NULL; | |||
for (Plugin *p : gPlugins) { | |||
if (p->slug == pluginSlug) { | |||
plugin = p; | |||
break; | |||
} | |||
} | |||
if (!plugin) { | |||
message += stringf("Could not find plugin \"%s\" for module \"%s\"\n", pluginSlug.c_str(), modelSlug.c_str()); | |||
continue; | |||
} | |||
// Search for model | |||
Model *model = NULL; | |||
for (Plugin *plugin : gPlugins) { | |||
for (Model *m : plugin->models) { | |||
if (m->manufacturerSlug == manufacturerSlug && m->slug == modelSlug) { | |||
model = m; | |||
} | |||
for (Model *m : plugin->models) { | |||
if (m->slug == modelSlug) { | |||
model = m; | |||
break; | |||
} | |||
} | |||
if (!model) { | |||
message += stringf("Could not find \"%s %s\" module\n", manufacturerSlug.c_str(), modelSlug.c_str()); | |||
message += stringf("Could not find module \"%s\" in plugin \"%s\"\n", pluginSlug.c_str(), modelSlug.c_str()); | |||
continue; | |||
} | |||
@@ -424,7 +433,7 @@ struct AddModuleMenuItem : MenuItem { | |||
}; | |||
struct AddManufacturerMenuItem : MenuItem { | |||
std::string manufacturerName; | |||
std::string manufacturer; | |||
Vec modulePos; | |||
void onAction(EventAction &e) override { | |||
e.consumed = false; | |||
@@ -435,7 +444,7 @@ struct AddManufacturerMenuItem : MenuItem { | |||
// Collect models which have this manufacturer name | |||
for (Plugin *plugin : gPlugins) { | |||
for (Model *model : plugin->models) { | |||
if (model->manufacturerName == manufacturerName) { | |||
if (model->manufacturer == manufacturer) { | |||
AddModuleMenuItem *item = new AddModuleMenuItem(); | |||
item->text = model->name; | |||
// item->rightText = model->plugin->slug; | |||
@@ -461,7 +470,7 @@ struct SearchModuleField : TextField { | |||
AddManufacturerMenuItem *a = dynamic_cast<AddManufacturerMenuItem*>(w); | |||
if (!a) | |||
continue; | |||
if (a->manufacturerName == text) { | |||
if (a->manufacturer == text) { | |||
a->visible = true; | |||
} | |||
else { | |||
@@ -491,17 +500,17 @@ void RackWidget::onMouseDown(EventMouseDown &e) { | |||
gFocusedWidget = searchField; | |||
// Collect manufacturer names | |||
std::set<std::string> manufacturerNames; | |||
std::set<std::string> manufacturers; | |||
for (Plugin *plugin : gPlugins) { | |||
for (Model *model : plugin->models) { | |||
manufacturerNames.insert(model->manufacturerName); | |||
manufacturers.insert(model->manufacturer); | |||
} | |||
} | |||
// Add menu item for each manufacturer name | |||
for (std::string manufacturerName : manufacturerNames) { | |||
for (std::string manufacturer : manufacturers) { | |||
AddManufacturerMenuItem *item = new AddManufacturerMenuItem(); | |||
item->text = manufacturerName; | |||
item->manufacturerName = manufacturerName; | |||
item->text = manufacturer; | |||
item->manufacturer = manufacturer; | |||
item->modulePos = e.pos; | |||
menu->addChild(item); | |||
} | |||
@@ -7,15 +7,15 @@ void init(rack::Plugin *p) { | |||
p->version = TOSTRING(VERSION); | |||
#endif | |||
p->addModel(createModel<AudioInterfaceWidget>("Core", "Core", "AudioInterface", "Audio Interface", EXTERNAL_TAG)); | |||
p->addModel(createModel<MidiToCVWidget>("Core", "Core", "MIDIToCVInterface", "MIDI-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
p->addModel(createModel<AudioInterfaceWidget>("Core", "AudioInterface", "Audio Interface", EXTERNAL_TAG)); | |||
p->addModel(createModel<MidiToCVWidget>("Core", "MIDIToCVInterface", "MIDI-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
p->addModel(createModel<MIDICCToCVWidget>("Core", "Core", "MIDICCToCVInterface", "MIDI CC-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
p->addModel(createModel<MIDIClockToCVWidget>("Core", "Core", "MIDIClockToCVInterface", "MIDI Clock-to-CV Interface", MIDI_TAG, EXTERNAL_TAG, CLOCK_TAG)); | |||
p->addModel(createModel<MIDITriggerToCVWidget>("Core", "Core", "MIDITriggerToCVInterface", "MIDI Trigger-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
p->addModel(createModel<QuadMidiToCVWidget>("Core", "Core", "QuadMIDIToCVInterface", "Quad MIDI-to-CV Interface", MIDI_TAG, EXTERNAL_TAG, QUAD_TAG)); | |||
p->addModel(createModel<MIDICCToCVWidget>("Core", "MIDICCToCVInterface", "MIDI CC-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
p->addModel(createModel<MIDIClockToCVWidget>("Core", "MIDIClockToCVInterface", "MIDI Clock-to-CV Interface", MIDI_TAG, EXTERNAL_TAG, CLOCK_TAG)); | |||
p->addModel(createModel<MIDITriggerToCVWidget>("Core", "MIDITriggerToCVInterface", "MIDI Trigger-to-CV Interface", MIDI_TAG, EXTERNAL_TAG)); | |||
p->addModel(createModel<QuadMidiToCVWidget>("Core", "QuadMIDIToCVInterface", "Quad MIDI-to-CV Interface", MIDI_TAG, EXTERNAL_TAG, QUAD_TAG)); | |||
// p->addModel(createModel<BridgeWidget>("Core", "Core", "Bridge", "Bridge")); | |||
p->addModel(createModel<BlankWidget>("Core", "Core", "Blank", "Blank", BLANK_TAG)); | |||
p->addModel(createModel<NotesWidget>("Core", "Core", "Notes", "Notes", BLANK_TAG)); | |||
// p->addModel(createModel<BridgeWidget>("Core", "Bridge", "Bridge")); | |||
p->addModel(createModel<BlankWidget>("Core", "Blank", "Blank", BLANK_TAG)); | |||
p->addModel(createModel<NotesWidget>("Core", "Notes", "Notes", BLANK_TAG)); | |||
} |