Browse Source

Move moduleFromJson from engine to plugin namespace. Move Engine mutex lock at the top of Engine::step().

tags/v2.0.0
Andrew Belt 5 years ago
parent
commit
12fcaa4b08
5 changed files with 72 additions and 49 deletions
  1. +0
    -6
      include/engine/Engine.hpp
  2. +4
    -0
      include/plugin.hpp
  3. +2
    -2
      src/app/RackWidget.cpp
  4. +22
    -41
      src/engine/Engine.cpp
  5. +44
    -0
      src/plugin.cpp

+ 0
- 6
include/engine/Engine.hpp View File

@@ -87,11 +87,5 @@ struct Engine {
}; };




/** Creates a Module from a JSON module object.
Throws an Exception if the model is not found.
*/
Module* moduleFromJson(json_t* moduleJ);


} // namespace engine } // namespace engine
} // namespace rack } // namespace rack

+ 4
- 0
include/plugin.hpp View File

@@ -34,6 +34,10 @@ void syncUpdates();
bool isSyncing(); bool isSyncing();
Plugin* getPlugin(const std::string& pluginSlug); Plugin* getPlugin(const std::string& pluginSlug);
Model* getModel(const std::string& pluginSlug, const std::string& modelSlug); Model* getModel(const std::string& pluginSlug, const std::string& modelSlug);
/** Creates a Module from a JSON module object.
Throws an Exception if the model is not found.
*/
engine::Module* moduleFromJson(json_t* moduleJ);
/** Checks that the slug contains only alphanumeric characters, "-", and "_" */ /** Checks that the slug contains only alphanumeric characters, "-", and "_" */
bool isSlugValid(const std::string& slug); bool isSlugValid(const std::string& slug);
/** Returns a string containing only the valid slug characters. */ /** Returns a string containing only the valid slug characters. */


+ 2
- 2
src/app/RackWidget.cpp View File

@@ -21,7 +21,7 @@ namespace app {


/** Creates a new Module and ModuleWidget */ /** Creates a new Module and ModuleWidget */
ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) { ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) {
engine::Module* module = engine::moduleFromJson(moduleJ);
engine::Module* module = plugin::moduleFromJson(moduleJ);
assert(module); assert(module);


// Create ModuleWidget // Create ModuleWidget
@@ -301,7 +301,7 @@ void RackWidget::pastePresetClipboardAction() {
}); });


try { try {
engine::Module* module = engine::moduleFromJson(moduleJ);
engine::Module* module = plugin::moduleFromJson(moduleJ);
// Reset ID so the Engine automatically assigns a new one // Reset ID so the Engine automatically assigns a new one
module->id = -1; module->id = -1;
APP->engine->addModule(module); APP->engine->addModule(module);


+ 22
- 41
src/engine/Engine.cpp View File

@@ -422,6 +422,7 @@ void Engine::clear() {




void Engine::step(int frames) { void Engine::step(int frames) {
std::lock_guard<std::recursive_mutex> lock(internal->mutex);
// Configure thread // Configure thread
initMXCSR(); initMXCSR();
random::init(); random::init();
@@ -444,8 +445,6 @@ void Engine::step(int frames) {
Engine_relaunchWorkers(this, settings::threadCount); Engine_relaunchWorkers(this, settings::threadCount);
} }


std::lock_guard<std::recursive_mutex> lock(internal->mutex);

// Update expander pointers // Update expander pointers
for (Module* module : internal->modules) { for (Module* module : internal->modules) {
Engine_updateExpander(this, &module->leftExpander); Engine_updateExpander(this, &module->leftExpander);
@@ -475,6 +474,7 @@ void Engine::setPrimaryModule(Module* module) {




Module* Engine::getPrimaryModule() { Module* Engine::getPrimaryModule() {
// No lock, for performance
return internal->primaryModule; return internal->primaryModule;
} }


@@ -486,17 +486,19 @@ void Engine::setPaused(bool paused) {




bool Engine::isPaused() { bool Engine::isPaused() {
// No lock
// No lock, for performance
return internal->paused; return internal->paused;
} }




float Engine::getSampleRate() { float Engine::getSampleRate() {
// No lock, for performance
return internal->sampleRate; return internal->sampleRate;
} }




float Engine::getSampleTime() { float Engine::getSampleTime() {
// No lock, for performance
return internal->sampleTime; return internal->sampleTime;
} }


@@ -507,13 +509,14 @@ void Engine::yieldWorkers() {




uint64_t Engine::getFrame() { uint64_t Engine::getFrame() {
// No lock, for performance
return internal->frame; return internal->frame;
} }




void Engine::addModule(Module* module) { void Engine::addModule(Module* module) {
assert(module);
std::lock_guard<std::recursive_mutex> lock(internal->mutex); std::lock_guard<std::recursive_mutex> lock(internal->mutex);
assert(module);
// Check that the module is not already added // Check that the module is not already added
auto it = std::find(internal->modules.begin(), internal->modules.end(), module); auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
assert(it == internal->modules.end()); assert(it == internal->modules.end());
@@ -547,8 +550,8 @@ void Engine::addModule(Module* module) {




void Engine::removeModule(Module* module) { void Engine::removeModule(Module* module) {
assert(module);
std::lock_guard<std::recursive_mutex> lock(internal->mutex); std::lock_guard<std::recursive_mutex> lock(internal->mutex);
assert(module);
// Check that the module actually exists // Check that the module actually exists
auto it = std::find(internal->modules.begin(), internal->modules.end(), module); auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
assert(it != internal->modules.end()); assert(it != internal->modules.end());
@@ -601,8 +604,8 @@ Module* Engine::getModule(int moduleId) {




void Engine::resetModule(Module* module) { void Engine::resetModule(Module* module) {
assert(module);
std::lock_guard<std::recursive_mutex> lock(internal->mutex); std::lock_guard<std::recursive_mutex> lock(internal->mutex);
assert(module);


Module::ResetEvent eReset; Module::ResetEvent eReset;
module->onReset(eReset); module->onReset(eReset);
@@ -610,8 +613,8 @@ void Engine::resetModule(Module* module) {




void Engine::randomizeModule(Module* module) { void Engine::randomizeModule(Module* module) {
assert(module);
std::lock_guard<std::recursive_mutex> lock(internal->mutex); std::lock_guard<std::recursive_mutex> lock(internal->mutex);
assert(module);


Module::RandomizeEvent eRandomize; Module::RandomizeEvent eRandomize;
module->onRandomize(eRandomize); module->onRandomize(eRandomize);
@@ -619,8 +622,8 @@ void Engine::randomizeModule(Module* module) {




void Engine::disableModule(Module* module, bool disabled) { void Engine::disableModule(Module* module, bool disabled) {
assert(module);
std::lock_guard<std::recursive_mutex> lock(internal->mutex); std::lock_guard<std::recursive_mutex> lock(internal->mutex);
assert(module);
if (module->disabled == disabled) if (module->disabled == disabled)
return; return;
// Clear outputs and set to 1 channel // Clear outputs and set to 1 channel
@@ -689,8 +692,8 @@ static void Engine_updateConnected(Engine* that) {




void Engine::addCable(Cable* cable) { void Engine::addCable(Cable* cable) {
assert(cable);
std::lock_guard<std::recursive_mutex> lock(internal->mutex); std::lock_guard<std::recursive_mutex> lock(internal->mutex);
assert(cable);
// Check cable properties // Check cable properties
assert(cable->inputModule); assert(cable->inputModule);
assert(cable->outputModule); assert(cable->outputModule);
@@ -744,8 +747,8 @@ void Engine::addCable(Cable* cable) {




void Engine::removeCable(Cable* cable) { void Engine::removeCable(Cable* cable) {
assert(cable);
std::lock_guard<std::recursive_mutex> lock(internal->mutex); std::lock_guard<std::recursive_mutex> lock(internal->mutex);
assert(cable);
// Check that the cable is already added // Check that the cable is already added
auto it = std::find(internal->cables.begin(), internal->cables.end(), cable); auto it = std::find(internal->cables.begin(), internal->cables.end(), cable);
assert(it != internal->cables.end()); assert(it != internal->cables.end());
@@ -791,7 +794,7 @@ Cable* Engine::getCable(int cableId) {




void Engine::setParam(Module* module, int paramId, float value) { void Engine::setParam(Module* module, int paramId, float value) {
// Don't lock because this is called too frequently.
// No lock, for performance
// If param is being smoothed, cancel smoothing. // If param is being smoothed, cancel smoothing.
if (internal->smoothModule == module && internal->smoothParamId == paramId) { if (internal->smoothModule == module && internal->smoothParamId == paramId) {
internal->smoothModule = NULL; internal->smoothModule = NULL;
@@ -802,11 +805,13 @@ void Engine::setParam(Module* module, int paramId, float value) {




float Engine::getParam(Module* module, int paramId) { float Engine::getParam(Module* module, int paramId) {
// No lock, for performance
return module->params[paramId].value; return module->params[paramId].value;
} }




void Engine::setSmoothParam(Module* module, int paramId, float value) { void Engine::setSmoothParam(Module* module, int paramId, float value) {
// No lock, for performance
// If another param is being smoothed, jump value // If another param is being smoothed, jump value
if (internal->smoothModule && !(internal->smoothModule == module && internal->smoothParamId == paramId)) { if (internal->smoothModule && !(internal->smoothModule == module && internal->smoothParamId == paramId)) {
internal->smoothModule->params[internal->smoothParamId].value = internal->smoothValue; internal->smoothModule->params[internal->smoothParamId].value = internal->smoothValue;
@@ -819,6 +824,7 @@ void Engine::setSmoothParam(Module* module, int paramId, float value) {




float Engine::getSmoothParam(Module* module, int paramId) { float Engine::getSmoothParam(Module* module, int paramId) {
// No lock, for performance
if (internal->smoothModule == module && internal->smoothParamId == paramId) if (internal->smoothModule == module && internal->smoothParamId == paramId)
return internal->smoothValue; return internal->smoothValue;
return getParam(module, paramId); return getParam(module, paramId);
@@ -868,8 +874,7 @@ void Engine::removeParamHandle(ParamHandle* paramHandle) {




ParamHandle* Engine::getParamHandle(int moduleId, int paramId) { ParamHandle* Engine::getParamHandle(int moduleId, int paramId) {
// Don't lock because this method is called potentially thousands of times per screen frame.

// No lock, for performance
auto it = internal->paramHandleCache.find(std::make_tuple(moduleId, paramId)); auto it = internal->paramHandleCache.find(std::make_tuple(moduleId, paramId));
if (it == internal->paramHandleCache.end()) if (it == internal->paramHandleCache.end())
return NULL; return NULL;
@@ -878,6 +883,7 @@ ParamHandle* Engine::getParamHandle(int moduleId, int paramId) {




ParamHandle* Engine::getParamHandle(Module* module, int paramId) { ParamHandle* Engine::getParamHandle(Module* module, int paramId) {
// No lock, for performance
return getParamHandle(module->id, paramId); return getParamHandle(module->id, paramId);
} }


@@ -922,6 +928,7 @@ void Engine::updateParamHandle(ParamHandle* paramHandle, int moduleId, int param




json_t* Engine::toJson() { json_t* Engine::toJson() {
std::lock_guard<std::recursive_mutex> lock(internal->mutex);
json_t* rootJ = json_object(); json_t* rootJ = json_object();


// modules // modules
@@ -947,6 +954,7 @@ json_t* Engine::toJson() {




void Engine::fromJson(json_t* rootJ) { void Engine::fromJson(json_t* rootJ) {
std::lock_guard<std::recursive_mutex> lock(internal->mutex);
// modules // modules
json_t* modulesJ = json_object_get(rootJ, "modules"); json_t* modulesJ = json_object_get(rootJ, "modules");
if (!modulesJ) if (!modulesJ)
@@ -955,7 +963,7 @@ void Engine::fromJson(json_t* rootJ) {
json_t* moduleJ; json_t* moduleJ;
json_array_foreach(modulesJ, moduleIndex, moduleJ) { json_array_foreach(modulesJ, moduleIndex, moduleJ) {
try { try {
Module* module = moduleFromJson(moduleJ);
Module* module = plugin::moduleFromJson(moduleJ);


// Before 1.0, the module ID was the index in the "modules" array // Before 1.0, the module ID was the index in the "modules" array
if (APP->patch->isLegacy(2)) { if (APP->patch->isLegacy(2)) {
@@ -1009,32 +1017,5 @@ void EngineWorker::run() {
} }




Module* moduleFromJson(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 = plugin::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 = plugin::normalizeSlug(modelSlug);

// Get Model
plugin::Model* model = plugin::getModel(pluginSlug, modelSlug);
if (!model)
throw Exception(string::f("Could not find module \"%s\" of plugin \"%s\"", modelSlug.c_str(), pluginSlug.c_str()));

// Create Module
Module* module = model->createModule();
assert(module);
module->fromJson(moduleJ);
return module;
}


} // namespace engine } // namespace engine
} // namespace rack } // namespace rack

+ 44
- 0
src/plugin.cpp View File

@@ -7,6 +7,7 @@
#include <app/common.hpp> #include <app/common.hpp>
#include <plugin/callbacks.hpp> #include <plugin/callbacks.hpp>
#include <settings.hpp> #include <settings.hpp>
#include <engine/Module.hpp>


#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -162,6 +163,7 @@ static Plugin* loadPlugin(std::string path) {
return plugin; return plugin;
} }



static void loadPlugins(std::string path) { static void loadPlugins(std::string path) {
for (std::string pluginPath : system::getEntries(path)) { for (std::string pluginPath : system::getEntries(path)) {
if (!system::isDirectory(pluginPath)) if (!system::isDirectory(pluginPath))
@@ -172,6 +174,7 @@ static void loadPlugins(std::string path) {
} }
} }



static void extractPackages(std::string path) { static void extractPackages(std::string path) {
std::string message; std::string message;


@@ -232,6 +235,7 @@ void init() {
} }
} }



void destroy() { void destroy() {
for (Plugin* plugin : plugins) { for (Plugin* plugin : plugins) {
// Free library handle // Free library handle
@@ -250,6 +254,7 @@ void destroy() {
plugins.clear(); plugins.clear();
} }



void logIn(const std::string& email, const std::string& password) { void logIn(const std::string& email, const std::string& password) {
loginStatus = "Logging in..."; loginStatus = "Logging in...";
json_t* reqJ = json_object(); json_t* reqJ = json_object();
@@ -286,15 +291,18 @@ void logIn(const std::string& email, const std::string& password) {
queryUpdates(); queryUpdates();
} }



void logOut() { void logOut() {
settings::token = ""; settings::token = "";
updates.clear(); updates.clear();
} }



bool isLoggedIn() { bool isLoggedIn() {
return settings::token != ""; return settings::token != "";
} }



void queryUpdates() { void queryUpdates() {
if (settings::token.empty()) if (settings::token.empty())
return; return;
@@ -392,6 +400,7 @@ void queryUpdates() {
updateStatus = ""; updateStatus = "";
} }



bool hasUpdates() { bool hasUpdates() {
for (Update& update : updates) { for (Update& update : updates) {
if (update.progress < 1.f) if (update.progress < 1.f)
@@ -400,9 +409,11 @@ bool hasUpdates() {
return false; return false;
} }



static bool isSyncingUpdate = false; static bool isSyncingUpdate = false;
static bool isSyncingUpdates = false; static bool isSyncingUpdates = false;



void syncUpdate(Update* update) { void syncUpdate(Update* update) {
isSyncingUpdate = true; isSyncingUpdate = true;
DEFER({ DEFER({
@@ -425,6 +436,7 @@ void syncUpdate(Update* update) {
} }
} }



void syncUpdates() { void syncUpdates() {
isSyncingUpdates = true; isSyncingUpdates = true;
DEFER({ DEFER({
@@ -441,10 +453,12 @@ void syncUpdates() {
restartRequested = true; restartRequested = true;
} }



bool isSyncing() { bool isSyncing() {
return isSyncingUpdate || isSyncingUpdates; return isSyncingUpdate || isSyncingUpdates;
} }



Plugin* getPlugin(const std::string& pluginSlug) { Plugin* getPlugin(const std::string& pluginSlug) {
for (Plugin* plugin : plugins) { for (Plugin* plugin : plugins) {
if (plugin->slug == pluginSlug) { if (plugin->slug == pluginSlug) {
@@ -454,6 +468,7 @@ Plugin* getPlugin(const std::string& pluginSlug) {
return NULL; return NULL;
} }



Model* getModel(const std::string& pluginSlug, const std::string& modelSlug) { Model* getModel(const std::string& pluginSlug, const std::string& modelSlug) {
Plugin* plugin = getPlugin(pluginSlug); Plugin* plugin = getPlugin(pluginSlug);
if (!plugin) if (!plugin)
@@ -464,6 +479,34 @@ Model* getModel(const std::string& pluginSlug, const std::string& modelSlug) {
return model; return model;
} }



engine::Module* moduleFromJson(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 = getModel(pluginSlug, modelSlug);
if (!model)
throw Exception(string::f("Could not find module \"%s\" of plugin \"%s\"", modelSlug.c_str(), pluginSlug.c_str()));

// Create Module
engine::Module* module = model->createModule();
assert(module);
module->fromJson(moduleJ);
return module;
}


bool isSlugValid(const std::string& slug) { bool isSlugValid(const std::string& slug) {
for (char c : slug) { for (char c : slug) {
if (!(std::isalnum(c) || c == '-' || c == '_')) if (!(std::isalnum(c) || c == '-' || c == '_'))
@@ -472,6 +515,7 @@ bool isSlugValid(const std::string& slug) {
return true; return true;
} }



std::string normalizeSlug(const std::string& slug) { std::string normalizeSlug(const std::string& slug) {
std::string s; std::string s;
for (char c : slug) { for (char c : slug) {


Loading…
Cancel
Save