slug for patches instead of manufacturerSlugtags/v0.5.0
@@ -66,19 +66,19 @@ struct Plugin { | |||||
/** OS-dependent library handle */ | /** OS-dependent library handle */ | ||||
void *handle = NULL; | 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; | 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 | 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. | Do not include the "v" in "v1.0" for example. | ||||
*/ | */ | ||||
std::string version; | std::string version; | ||||
/** URL for plugin homepage */ | |||||
/** URL for plugin homepage (optional) */ | |||||
std::string website; | std::string website; | ||||
/** URL for plugin manual */ | |||||
/** URL for plugin manual (optional) */ | |||||
std::string manual; | std::string manual; | ||||
virtual ~Plugin(); | virtual ~Plugin(); | ||||
@@ -91,11 +91,12 @@ struct Model { | |||||
std::string slug; | std::string slug; | ||||
/** Human readable name for your model, e.g. "Voltage Controlled Oscillator" */ | /** Human readable name for your model, e.g. "Voltage Controlled Oscillator" */ | ||||
std::string name; | 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; | std::list<ModelTag> tags; | ||||
virtual ~Model() {} | virtual ~Model() {} | ||||
@@ -19,7 +19,7 @@ namespace rack { | |||||
template <class TModuleWidget, typename... Tags> | 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 { | struct TModel : Model { | ||||
ModuleWidget *createModuleWidget() override { | ModuleWidget *createModuleWidget() override { | ||||
ModuleWidget *moduleWidget = new TModuleWidget(); | ModuleWidget *moduleWidget = new TModuleWidget(); | ||||
@@ -28,10 +28,9 @@ Model *createModel(std::string manufacturerSlug, std::string manufacturerName, s | |||||
} | } | ||||
}; | }; | ||||
Model *model = new TModel(); | Model *model = new TModel(); | ||||
model->manufacturer = manufacturer; | |||||
model->slug = slug; | model->slug = slug; | ||||
model->name = name; | model->name = name; | ||||
model->manufacturerSlug = manufacturerSlug; | |||||
model->manufacturerName = manufacturerName; | |||||
model->tags = {tags...}; | model->tags = {tags...}; | ||||
return model; | return model; | ||||
} | } | ||||
@@ -61,7 +61,7 @@ json_t *ModuleWidget::toJson() { | |||||
json_t *rootJ = json_object(); | json_t *rootJ = json_object(); | ||||
// manufacturer | // 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 | // model | ||||
json_object_set_new(rootJ, "model", json_string(model->slug.c_str())); | json_object_set_new(rootJ, "model", json_string(model->slug.c_str())); | ||||
// pos | // pos | ||||
@@ -278,7 +278,7 @@ Menu *ModuleWidget::createContextMenu() { | |||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
MenuLabel *menuLabel = new MenuLabel(); | MenuLabel *menuLabel = new MenuLabel(); | ||||
menuLabel->text = model->manufacturerName + " " + model->name; | |||||
menuLabel->text = model->manufacturer + " " + model->name; | |||||
menu->pushChild(menuLabel); | menu->pushChild(menuLabel); | ||||
ResetMenuItem *resetItem = new ResetMenuItem(); | ResetMenuItem *resetItem = new ResetMenuItem(); | ||||
@@ -204,29 +204,38 @@ void RackWidget::fromJson(json_t *rootJ) { | |||||
size_t moduleId; | size_t moduleId; | ||||
json_t *moduleJ; | json_t *moduleJ; | ||||
json_array_foreach(modulesJ, moduleId, 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"); | json_t *modelSlugJ = json_object_get(moduleJ, "model"); | ||||
if (!modelSlugJ) continue; | if (!modelSlugJ) continue; | ||||
std::string manufacturerSlug = json_string_value(manufacturerSlugJ); | |||||
std::string pluginSlug = json_string_value(pluginSlugJ); | |||||
std::string modelSlug = json_string_value(modelSlugJ); | 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 | // Search for model | ||||
Model *model = NULL; | 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) { | 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; | continue; | ||||
} | } | ||||
@@ -424,7 +433,7 @@ struct AddModuleMenuItem : MenuItem { | |||||
}; | }; | ||||
struct AddManufacturerMenuItem : MenuItem { | struct AddManufacturerMenuItem : MenuItem { | ||||
std::string manufacturerName; | |||||
std::string manufacturer; | |||||
Vec modulePos; | Vec modulePos; | ||||
void onAction(EventAction &e) override { | void onAction(EventAction &e) override { | ||||
e.consumed = false; | e.consumed = false; | ||||
@@ -435,7 +444,7 @@ struct AddManufacturerMenuItem : MenuItem { | |||||
// Collect models which have this manufacturer name | // Collect models which have this manufacturer name | ||||
for (Plugin *plugin : gPlugins) { | for (Plugin *plugin : gPlugins) { | ||||
for (Model *model : plugin->models) { | for (Model *model : plugin->models) { | ||||
if (model->manufacturerName == manufacturerName) { | |||||
if (model->manufacturer == manufacturer) { | |||||
AddModuleMenuItem *item = new AddModuleMenuItem(); | AddModuleMenuItem *item = new AddModuleMenuItem(); | ||||
item->text = model->name; | item->text = model->name; | ||||
// item->rightText = model->plugin->slug; | // item->rightText = model->plugin->slug; | ||||
@@ -461,7 +470,7 @@ struct SearchModuleField : TextField { | |||||
AddManufacturerMenuItem *a = dynamic_cast<AddManufacturerMenuItem*>(w); | AddManufacturerMenuItem *a = dynamic_cast<AddManufacturerMenuItem*>(w); | ||||
if (!a) | if (!a) | ||||
continue; | continue; | ||||
if (a->manufacturerName == text) { | |||||
if (a->manufacturer == text) { | |||||
a->visible = true; | a->visible = true; | ||||
} | } | ||||
else { | else { | ||||
@@ -491,17 +500,17 @@ void RackWidget::onMouseDown(EventMouseDown &e) { | |||||
gFocusedWidget = searchField; | gFocusedWidget = searchField; | ||||
// Collect manufacturer names | // Collect manufacturer names | ||||
std::set<std::string> manufacturerNames; | |||||
std::set<std::string> manufacturers; | |||||
for (Plugin *plugin : gPlugins) { | for (Plugin *plugin : gPlugins) { | ||||
for (Model *model : plugin->models) { | for (Model *model : plugin->models) { | ||||
manufacturerNames.insert(model->manufacturerName); | |||||
manufacturers.insert(model->manufacturer); | |||||
} | } | ||||
} | } | ||||
// Add menu item for each manufacturer name | // Add menu item for each manufacturer name | ||||
for (std::string manufacturerName : manufacturerNames) { | |||||
for (std::string manufacturer : manufacturers) { | |||||
AddManufacturerMenuItem *item = new AddManufacturerMenuItem(); | AddManufacturerMenuItem *item = new AddManufacturerMenuItem(); | ||||
item->text = manufacturerName; | |||||
item->manufacturerName = manufacturerName; | |||||
item->text = manufacturer; | |||||
item->manufacturer = manufacturer; | |||||
item->modulePos = e.pos; | item->modulePos = e.pos; | ||||
menu->addChild(item); | menu->addChild(item); | ||||
} | } | ||||
@@ -7,15 +7,15 @@ void init(rack::Plugin *p) { | |||||
p->version = TOSTRING(VERSION); | p->version = TOSTRING(VERSION); | ||||
#endif | #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)); | |||||
} | } |