1
Fork 0

Stop building Rack core audio and midi, setup Cardinal replacements

Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
falkTX 2022-01-23 22:57:11 +00:00
parent 5d39ab42cb
commit c4609cba06
No known key found for this signature in database
GPG Key ID: CDBAA37ABC74FBA0
7 changed files with 550 additions and 71 deletions

View File

@ -12,48 +12,6 @@
"changelogUrl": "https://github.com/VCVRack/Rack/blob/v2/CHANGELOG.md",
"description": "Necessary modules built into Cardinal",
"modules": [
{
"slug": "AudioInterface2",
"name": "Audio 2",
"description": "Sends audio and CV to/from an audio device",
"manualUrl": "https://vcvrack.com/manual/Core#Audio",
"tags": [
"External"
],
"hidden": true
},
{
"slug": "AudioInterface",
"name": "Audio 8",
"description": "Sends audio and CV to/from an audio device",
"manualUrl": "https://vcvrack.com/manual/Core#Audio",
"tags": [
"External"
],
"hidden": true
},
{
"slug": "AudioInterface16",
"name": "Audio 16",
"description": "Sends audio and CV to/from an audio device",
"manualUrl": "https://vcvrack.com/manual/Core#Audio",
"tags": [
"External"
],
"hidden": true
},
{
"slug": "MIDIToCVInterface",
"name": "MIDI to CV",
"description": "Converts MIDI from an external device to CV and gates",
"manualUrl": "https://vcvrack.com/manual/Core#MIDI-CV",
"tags": [
"External",
"MIDI",
"Polyphonic"
],
"hidden": true
},
{
"slug": "MIDICCToCVInterface",
"name": "MIDI CC to CV",
@ -84,18 +42,6 @@
"MIDI"
]
},
{
"slug": "CV-MIDI",
"name": "CV to MIDI",
"description": "Converts CV to MIDI and sends to an external device",
"manualUrl": "https://vcvrack.com/manual/Core#CV-MIDI",
"tags": [
"External",
"MIDI",
"Polyphonic"
],
"hidden": true
},
{
"slug": "CV-CC",
"name": "CV to MIDI CC",

View File

@ -567,14 +567,9 @@ std::string pluginPath(const std::string& dirname);
// core plugins
namespace core {
extern Model* modelAudio2;
extern Model* modelAudio8;
extern Model* modelAudio16;
extern Model* modelMIDI_CV;
extern Model* modelMIDICC_CV;
extern Model* modelMIDI_Gate;
extern Model* modelMIDIMap;
extern Model* modelCV_MIDI;
extern Model* modelCV_MIDICC;
extern Model* modelGate_MIDI;
extern Model* modelBlank;
@ -670,14 +665,9 @@ static void initStatic__Core()
const StaticPluginLoader spl(p, "Core");
if (spl.ok())
{
p->addModel(rack::core::modelAudio2);
p->addModel(rack::core::modelAudio8);
p->addModel(rack::core::modelAudio16);
p->addModel(rack::core::modelMIDI_CV);
p->addModel(rack::core::modelMIDICC_CV);
p->addModel(rack::core::modelMIDI_Gate);
p->addModel(rack::core::modelMIDIMap);
p->addModel(rack::core::modelCV_MIDI);
p->addModel(rack::core::modelCV_MIDICC);
p->addModel(rack::core::modelGate_MIDI);
p->addModel(rack::core::modelBlank);

View File

@ -102,6 +102,7 @@ RACK_FILES += custom/network.cpp
RACK_FILES += custom/osdialog.cpp
RACK_FILES += override/blendish.c
RACK_FILES += override/context.cpp
RACK_FILES += override/plugin.cpp
RACK_FILES += override/Engine.cpp
RACK_FILES += override/MenuBar.cpp
RACK_FILES += override/Model.cpp
@ -120,11 +121,15 @@ IGNORED_FILES += Rack/src/gamepad.cpp
IGNORED_FILES += Rack/src/keyboard.cpp
IGNORED_FILES += Rack/src/library.cpp
IGNORED_FILES += Rack/src/network.cpp
IGNORED_FILES += Rack/src/plugin.cpp
IGNORED_FILES += Rack/src/rtaudio.cpp
IGNORED_FILES += Rack/src/rtmidi.cpp
IGNORED_FILES += Rack/src/app/MenuBar.cpp
IGNORED_FILES += Rack/src/app/Scene.cpp
IGNORED_FILES += Rack/src/app/TipWindow.cpp
IGNORED_FILES += Rack/src/core/Audio.cpp
IGNORED_FILES += Rack/src/core/CV_MIDI.cpp
IGNORED_FILES += Rack/src/core/MIDI_CV.cpp
IGNORED_FILES += Rack/src/engine/Engine.cpp
IGNORED_FILES += Rack/src/plugin/Model.cpp
IGNORED_FILES += Rack/src/window/Window.cpp

View File

@ -5,6 +5,7 @@ set -e
diff -U3 ../Rack/dep/oui-blendish/blendish.c blendish.c > diffs/blendish.c.diff
diff -U3 ../Rack/src/common.cpp common.cpp > diffs/common.cpp.diff
diff -U3 ../Rack/src/context.cpp context.cpp > diffs/context.cpp.diff
diff -U3 ../Rack/src/plugin.cpp plugin.cpp > diffs/plugin.cpp.diff
diff -U3 ../Rack/src/app/MenuBar.cpp MenuBar.cpp > diffs/MenuBar.cpp.diff
diff -U3 ../Rack/src/app/Scene.cpp Scene.cpp > diffs/Scene.cpp.diff
diff -U3 ../Rack/src/engine/Engine.cpp Engine.cpp > diffs/Engine.cpp.diff

View File

@ -0,0 +1,359 @@
--- ../Rack/src/plugin.cpp 2022-01-15 14:44:46.395281005 +0000
+++ plugin.cpp 2022-01-23 22:59:41.770256440 +0000
@@ -1,308 +1,40 @@
-#include <thread>
-#include <map>
-#include <stdexcept>
-#include <tuple>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/param.h> // for MAXPATHLEN
-#include <fcntl.h>
-#if defined ARCH_WIN
- #include <windows.h>
- #include <direct.h>
-#else
- #include <dlfcn.h> // for dlopen
-#endif
-#include <dirent.h>
+/*
+ * DISTRHO Cardinal Plugin
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * For a full copy of the GNU General Public License see the LICENSE file.
+ */
+
+/**
+ * This file is an edited version of VCVRack's plugin.cpp
+ * Copyright (C) 2016-2021 VCV.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ */
-#include <osdialog.h>
-#include <jansson.h>
+#include <algorithm>
+#include <map>
#include <plugin.hpp>
-#include <system.hpp>
-#include <asset.hpp>
-#include <string.hpp>
-#include <context.hpp>
-#include <plugin/callbacks.hpp>
-#include <settings.hpp>
namespace rack {
-
-namespace core {
-void init(rack::plugin::Plugin* plugin);
-} // namespace core
-
namespace plugin {
-////////////////////
-// private API
-////////////////////
-
-/** Returns library handle */
-static void* loadLibrary(std::string libraryPath) {
-#if defined ARCH_WIN
- SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
- std::wstring libraryFilenameW = string::UTF8toUTF16(libraryPath);
- HINSTANCE handle = LoadLibraryW(libraryFilenameW.c_str());
- SetErrorMode(0);
- if (!handle) {
- int error = GetLastError();
- throw Exception("Failed to load library %s: code %d", libraryPath.c_str(), error);
- }
-#else
- // Since Rack 2, plugins on Linux/Mac link to the absolute path /tmp/Rack2/libRack.<ext>
- // Create a symlink at /tmp/Rack2 to the system dir containting libRack.
- std::string systemDir = system::getAbsolute(asset::systemDir);
- std::string linkPath = "/tmp/Rack2";
- if (!settings::devMode) {
- // Clean up old symbolic link in case a different edition was run earlier
- system::remove(linkPath);
- system::createSymbolicLink(systemDir, linkPath);
- }
- // Load library with dlopen
- void* handle = NULL;
- #if defined ARCH_LIN
- handle = dlopen(libraryPath.c_str(), RTLD_NOW | RTLD_LOCAL);
- #elif defined ARCH_MAC
- handle = dlopen(libraryPath.c_str(), RTLD_NOW | RTLD_LOCAL);
- #endif
- if (!settings::devMode) {
- system::remove(linkPath);
- }
- if (!handle)
- throw Exception("Failed to load library %s: %s", libraryPath.c_str(), dlerror());
-#endif
- return handle;
-}
-
-typedef void (*InitCallback)(Plugin*);
-
-static InitCallback loadPluginCallback(Plugin* plugin) {
- // Load plugin library
- std::string libraryExt;
-#if defined ARCH_LIN
- libraryExt = "so";
-#elif defined ARCH_WIN
- libraryExt = "dll";
-#elif ARCH_MAC
- libraryExt = "dylib";
-#endif
- std::string libraryPath = system::join(plugin->path, "plugin." + libraryExt);
-
- // Check file existence
- if (!system::isFile(libraryPath))
- throw Exception("Plugin binary not found at %s", libraryPath.c_str());
-
- // Load dynamic/shared library
- plugin->handle = loadLibrary(libraryPath);
-
- // Get plugin's init() function
- InitCallback initCallback;
-#if defined ARCH_WIN
- initCallback = (InitCallback) GetProcAddress((HMODULE) plugin->handle, "init");
-#else
- initCallback = (InitCallback) dlsym(plugin->handle, "init");
-#endif
- if (!initCallback)
- throw Exception("Failed to read init() symbol in %s", libraryPath.c_str());
-
- return initCallback;
-}
-
-
-/** If path is blank, loads Core */
-static Plugin* loadPlugin(std::string path) {
- if (path == "")
- INFO("Loading Core plugin");
- else
- INFO("Loading plugin from %s", path.c_str());
-
- Plugin* plugin = new Plugin;
- try {
- // Set plugin path
- plugin->path = (path == "") ? asset::systemDir : path;
-
- // Get modified timestamp
- if (path != "") {
- struct stat statbuf;
- if (!stat(path.c_str(), &statbuf)) {
-#if defined ARCH_MAC
- plugin->modifiedTimestamp = (double) statbuf.st_mtimespec.tv_sec + statbuf.st_mtimespec.tv_nsec * 1e-9;
-#elif defined ARCH_WIN
- plugin->modifiedTimestamp = (double) statbuf.st_mtime;
-#elif defined ARCH_LIN
- plugin->modifiedTimestamp = (double) statbuf.st_mtim.tv_sec + statbuf.st_mtim.tv_nsec * 1e-9;
-#endif
- }
- }
-
- // Load plugin.json
- std::string manifestFilename = (path == "") ? asset::system("Core.json") : system::join(path, "plugin.json");
- FILE* file = std::fopen(manifestFilename.c_str(), "r");
- if (!file)
- throw Exception("Manifest file %s does not exist", manifestFilename.c_str());
- DEFER({std::fclose(file);});
-
- json_error_t error;
- json_t* rootJ = json_loadf(file, 0, &error);
- if (!rootJ)
- throw Exception("JSON parsing error at %s %d:%d %s", manifestFilename.c_str(), error.line, error.column, error.text);
- DEFER({json_decref(rootJ);});
-
- // Call init callback
- InitCallback initCallback;
- if (path == "") {
- initCallback = core::init;
- }
- else {
- initCallback = loadPluginCallback(plugin);
- }
- initCallback(plugin);
-
- // Load manifest
- plugin->fromJson(rootJ);
-
- // Reject plugin if slug already exists
- Plugin* existingPlugin = getPlugin(plugin->slug);
- if (existingPlugin)
- throw Exception("Plugin %s is already loaded, not attempting to load it again", plugin->slug.c_str());
- }
- catch (Exception& e) {
- WARN("Could not load plugin %s: %s", path.c_str(), e.what());
- delete plugin;
- return NULL;
- }
-
- INFO("Loaded %s v%s", plugin->slug.c_str(), plugin->version.c_str());
- plugins.push_back(plugin);
- return plugin;
-}
-
-
-static void loadPlugins(std::string path) {
- for (std::string pluginPath : system::getEntries(path)) {
- if (!system::isDirectory(pluginPath))
- continue;
- if (!loadPlugin(pluginPath)) {
- // Ignore bad plugins. They are reported in the log.
- }
- }
-}
-
-
-static void extractPackages(std::string path) {
- std::string message;
-
- for (std::string packagePath : system::getEntries(path)) {
- if (!system::isFile(packagePath))
- continue;
- if (system::getExtension(packagePath) != ".vcvplugin")
- continue;
-
- // Extract package
- INFO("Extracting package %s", packagePath.c_str());
- try {
- system::unarchiveToDirectory(packagePath, path);
- }
- catch (Exception& e) {
- WARN("Plugin package %s failed to extract: %s", packagePath.c_str(), e.what());
- message += string::f("Could not extract plugin package %s\n", packagePath.c_str());
- continue;
- }
- // Remove package
- system::remove(packagePath.c_str());
- }
- if (!message.empty()) {
- osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, message.c_str());
- }
-}
-
-////////////////////
-// public API
-////////////////////
-
-void init() {
- // Don't re-initialize
- assert(plugins.empty());
-
- // Load Core
- loadPlugin("");
-
- pluginsPath = asset::user("plugins");
-
- // Get user plugins directory
- system::createDirectory(pluginsPath);
-
- // Extract packages and load plugins
- extractPackages(pluginsPath);
- loadPlugins(pluginsPath);
-
- // If Fundamental wasn't loaded, copy the bundled Fundamental package and load it
- if (!settings::devMode && !getPlugin("Fundamental")) {
- std::string fundamentalSrc = asset::system("Fundamental.vcvplugin");
- std::string fundamentalDir = system::join(pluginsPath, "Fundamental");
- if (system::isFile(fundamentalSrc)) {
- INFO("Extracting bundled Fundamental package");
- try {
- system::unarchiveToDirectory(fundamentalSrc.c_str(), pluginsPath.c_str());
- loadPlugin(fundamentalDir);
- }
- catch (Exception& e) {
- WARN("Could not extract Fundamental package: %s", e.what());
- }
- }
- }
-}
-
-
-static void destroyPlugin(Plugin* plugin) {
- void* handle = plugin->handle;
-
- // Call destroy() if defined in the plugin library
- typedef void (*DestroyCallback)();
- DestroyCallback destroyCallback = NULL;
- if (handle) {
-#if defined ARCH_WIN
- destroyCallback = (DestroyCallback) GetProcAddress((HMODULE) handle, "destroy");
-#else
- destroyCallback = (DestroyCallback) dlsym(handle, "destroy");
-#endif
- }
- if (destroyCallback) {
- try {
- destroyCallback();
- }
- catch (Exception& e) {
- WARN("Could not destroy plugin %s", plugin->slug.c_str());
- }
- }
-
- // We must delete the Plugin instance *before* freeing the library, because the vtables of Model subclasses are defined in the library, which are needed in the Plugin destructor.
- delete plugin;
-
- // Free library handle
- if (handle) {
-#if defined ARCH_WIN
- FreeLibrary((HINSTANCE) handle);
-#else
- dlclose(handle);
-#endif
- }
-}
-
-
-void destroy() {
- for (Plugin* plugin : plugins) {
- INFO("Destroying plugin %s", plugin->name.c_str());
- destroyPlugin(plugin);
- }
- plugins.clear();
-}
-
-
/** Given slug => fallback slug.
Correctly handles bidirectional fallbacks.
To request fallback slugs to be added to this list, open a GitHub issue.
@@ -352,6 +84,11 @@
*/
using PluginModuleSlug = std::tuple<std::string, std::string>;
static const std::map<PluginModuleSlug, PluginModuleSlug> moduleSlugFallbacks = {
+ {{"Core", "AudioInterface2"}, {"Cardinal", "HostAudio2"}},
+ {{"Core", "AudioInterface"}, {"Cardinal", "HostAudio8"}},
+ {{"Core", "AudioInterface16"}, {"Cardinal", "HostAudio8"}},
+ {{"Core", "MIDIToCVInterface"}, {"Cardinal", "HostMIDI"}},
+ {{"Core", "CV-MIDI"}, {"Cardinal", "HostMIDI"}},
{{"MindMeld-ShapeMasterPro", "ShapeMasterPro"}, {"MindMeldModular", "ShapeMaster"}},
{{"MindMeldModular", "ShapeMaster"}, {"MindMeld-ShapeMasterPro", "ShapeMasterPro"}},
// {{"", ""}, {"", ""}},
@@ -441,7 +178,6 @@
}
-std::string pluginsPath;
std::vector<Plugin*> plugins;

185
src/override/plugin.cpp Normal file
View File

@ -0,0 +1,185 @@
/*
* DISTRHO Cardinal Plugin
* Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the LICENSE file.
*/
/**
* This file is an edited version of VCVRack's plugin.cpp
* Copyright (C) 2016-2021 VCV.
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*/
#include <algorithm>
#include <map>
#include <plugin.hpp>
namespace rack {
namespace plugin {
/** Given slug => fallback slug.
Correctly handles bidirectional fallbacks.
To request fallback slugs to be added to this list, open a GitHub issue.
*/
static const std::map<std::string, std::string> pluginSlugFallbacks = {
{"VultModulesFree", "VultModules"},
{"VultModules", "VultModulesFree"},
{"AudibleInstrumentsPreview", "AudibleInstruments"},
// {"", ""},
};
Plugin* getPlugin(const std::string& pluginSlug) {
if (pluginSlug.empty())
return NULL;
auto it = std::find_if(plugins.begin(), plugins.end(), [=](Plugin* p) {
return p->slug == pluginSlug;
});
if (it != plugins.end())
return *it;
return NULL;
}
Plugin* getPluginFallback(const std::string& pluginSlug) {
if (pluginSlug.empty())
return NULL;
// Attempt example plugin
Plugin* p = getPlugin(pluginSlug);
if (p)
return p;
// Attempt fallback plugin slug
auto it = pluginSlugFallbacks.find(pluginSlug);
if (it != pluginSlugFallbacks.end())
return getPlugin(it->second);
return NULL;
}
/** Given slug => fallback slug.
Correctly handles bidirectional fallbacks.
To request fallback slugs to be added to this list, open a GitHub issue.
*/
using PluginModuleSlug = std::tuple<std::string, std::string>;
static const std::map<PluginModuleSlug, PluginModuleSlug> moduleSlugFallbacks = {
{{"Core", "AudioInterface2"}, {"Cardinal", "HostAudio2"}},
{{"Core", "AudioInterface"}, {"Cardinal", "HostAudio8"}},
{{"Core", "AudioInterface16"}, {"Cardinal", "HostAudio8"}},
{{"Core", "MIDIToCVInterface"}, {"Cardinal", "HostMIDI"}},
{{"Core", "CV-MIDI"}, {"Cardinal", "HostMIDI"}},
{{"MindMeld-ShapeMasterPro", "ShapeMasterPro"}, {"MindMeldModular", "ShapeMaster"}},
{{"MindMeldModular", "ShapeMaster"}, {"MindMeld-ShapeMasterPro", "ShapeMasterPro"}},
// {{"", ""}, {"", ""}},
};
Model* getModel(const std::string& pluginSlug, const std::string& modelSlug) {
if (pluginSlug.empty() || modelSlug.empty())
return NULL;
Plugin* p = getPlugin(pluginSlug);
if (!p)
return NULL;
return p->getModel(modelSlug);
}
Model* getModelFallback(const std::string& pluginSlug, const std::string& modelSlug) {
if (pluginSlug.empty() || modelSlug.empty())
return NULL;
// Attempt exact plugin and model
Model* m = getModel(pluginSlug, modelSlug);
if (m)
return m;
// Attempt fallback module
auto it = moduleSlugFallbacks.find(std::make_tuple(pluginSlug, modelSlug));
if (it != moduleSlugFallbacks.end()) {
Model* m = getModel(std::get<0>(it->second), std::get<1>(it->second));
if (m)
return m;
}
// Attempt fallback plugin
auto it2 = pluginSlugFallbacks.find(pluginSlug);
if (it2 != pluginSlugFallbacks.end()) {
Model* m = getModel(it2->second, modelSlug);
if (m)
return m;
}
return NULL;
}
Model* modelFromJson(json_t* moduleJ) {
// Get slugs
json_t* pluginSlugJ = json_object_get(moduleJ, "plugin");
if (!pluginSlugJ)
throw Exception("\"plugin\" property not found in module JSON");
std::string pluginSlug = json_string_value(pluginSlugJ);
pluginSlug = normalizeSlug(pluginSlug);
json_t* modelSlugJ = json_object_get(moduleJ, "model");
if (!modelSlugJ)
throw Exception("\"model\" property not found in module JSON");
std::string modelSlug = json_string_value(modelSlugJ);
modelSlug = normalizeSlug(modelSlug);
// Get Model
Model* model = getModelFallback(pluginSlug, modelSlug);
if (!model)
throw Exception("Could not find module %s/%s", pluginSlug.c_str(), modelSlug.c_str());
return model;
}
bool isSlugValid(const std::string& slug) {
for (char c : slug) {
if (!(std::isalnum(c) || c == '-' || c == '_'))
return false;
}
return true;
}
std::string normalizeSlug(const std::string& slug) {
std::string s;
for (char c : slug) {
if (!(std::isalnum(c) || c == '-' || c == '_'))
continue;
s += c;
}
return s;
}
std::vector<Plugin*> plugins;
} // namespace plugin
} // namespace rack

View File

@ -30,13 +30,6 @@
"params": [],
"leftModuleId": 1,
"rightModuleId": 3,
"data": {
"channels": 1,
"polyMode": 0,
"clockDivision": 24,
"lastPitch": 8192,
"lastMod": 0
},
"pos": [
5,
0