@@ -62,6 +62,7 @@ In this document, Mod is Ctrl on Windows/Linux and Cmd on Mac. | |||||
- Improve thread safety of `dsp::RingBuffer`. | - Improve thread safety of `dsp::RingBuffer`. | ||||
- Add several convenient filesystem routines to `system::`. | - Add several convenient filesystem routines to `system::`. | ||||
- Move all `string::` functions dealing with filesystem paths to `system::`. | - Move all `string::` functions dealing with filesystem paths to `system::`. | ||||
- Change type of `Module::id` and `Cable::id` from `int` to `int64_t`. | |||||
### 1.1.6 (2019-11-04) | ### 1.1.6 (2019-11-04) | ||||
- Add ability for plugins to use LuaJIT on Mac. | - Add ability for plugins to use LuaJIT on Mac. | ||||
@@ -57,7 +57,7 @@ struct RackWidget : widget::OpaqueWidget { | |||||
/** Moves a module to the closest non-colliding position */ | /** Moves a module to the closest non-colliding position */ | ||||
void setModulePosNearest(ModuleWidget* mw, math::Vec pos); | void setModulePosNearest(ModuleWidget* mw, math::Vec pos); | ||||
void setModulePosForce(ModuleWidget* mw, math::Vec pos); | void setModulePosForce(ModuleWidget* mw, math::Vec pos); | ||||
ModuleWidget* getModule(int moduleId); | |||||
ModuleWidget* getModule(int64_t moduleId); | |||||
bool isEmpty(); | bool isEmpty(); | ||||
void updateModuleOldPositions(); | void updateModuleOldPositions(); | ||||
history::ComplexAction* getModuleDragAction(); | history::ComplexAction* getModuleDragAction(); | ||||
@@ -78,7 +78,7 @@ struct RackWidget : widget::OpaqueWidget { | |||||
CableWidget* releaseIncompleteCable(); | CableWidget* releaseIncompleteCable(); | ||||
/** Returns the most recently added complete cable connected to the given Port, i.e. the top of the stack. */ | /** Returns the most recently added complete cable connected to the given Port, i.e. the top of the stack. */ | ||||
CableWidget* getTopCable(PortWidget* port); | CableWidget* getTopCable(PortWidget* port); | ||||
CableWidget* getCable(int cableId); | |||||
CableWidget* getCable(int64_t cableId); | |||||
/** Returns all cables attached to port, complete or not. */ | /** Returns all cables attached to port, complete or not. */ | ||||
std::list<CableWidget*> getCablesOnPort(PortWidget* port); | std::list<CableWidget*> getCablesOnPort(PortWidget* port); | ||||
}; | }; | ||||
@@ -67,8 +67,12 @@ struct Engine { | |||||
// Modules | // Modules | ||||
size_t getNumModules(); | size_t getNumModules(); | ||||
void getModuleIds(int* moduleIds, int len); | |||||
std::vector<int> getModuleIds(); | |||||
/** Fills `moduleIds` with up to `len` module IDs in the rack. | |||||
Returns the number of IDs written. | |||||
This C-like method does no allocations. The vector C++ version below does. | |||||
*/ | |||||
size_t getModuleIds(int64_t* moduleIds, size_t len); | |||||
std::vector<int64_t> getModuleIds(); | |||||
/** Adds a module to the rack engine. | /** Adds a module to the rack engine. | ||||
The module ID must not be taken by another module. | The module ID must not be taken by another module. | ||||
If the module ID is -1, an ID is automatically assigned. | If the module ID is -1, an ID is automatically assigned. | ||||
@@ -76,7 +80,7 @@ struct Engine { | |||||
*/ | */ | ||||
void addModule(Module* module); | void addModule(Module* module); | ||||
void removeModule(Module* module); | void removeModule(Module* module); | ||||
Module* getModule(int moduleId); | |||||
Module* getModule(int64_t moduleId); | |||||
void resetModule(Module* module); | void resetModule(Module* module); | ||||
void randomizeModule(Module* module); | void randomizeModule(Module* module); | ||||
void bypassModule(Module* module, bool bypassed); | void bypassModule(Module* module, bool bypassed); | ||||
@@ -86,6 +90,9 @@ struct Engine { | |||||
void moduleFromJson(Module* module, json_t* rootJ); | void moduleFromJson(Module* module, json_t* rootJ); | ||||
// Cables | // Cables | ||||
size_t getNumCables(); | |||||
size_t getCableIds(int64_t* cableIds, size_t len); | |||||
std::vector<int64_t> getCableIds(); | |||||
/** Adds a cable to the rack engine. | /** Adds a cable to the rack engine. | ||||
The cable ID must not be taken by another cable. | The cable ID must not be taken by another cable. | ||||
If the cable ID is -1, an ID is automatically assigned. | If the cable ID is -1, an ID is automatically assigned. | ||||
@@ -93,7 +100,7 @@ struct Engine { | |||||
*/ | */ | ||||
void addCable(Cable* cable); | void addCable(Cable* cable); | ||||
void removeCable(Cable* cable); | void removeCable(Cable* cable); | ||||
Cable* getCable(int cableId); | |||||
Cable* getCable(int64_t cableId); | |||||
// Params | // Params | ||||
void setParam(Module* module, int paramId, float value); | void setParam(Module* module, int paramId, float value); | ||||
@@ -110,14 +117,13 @@ struct Engine { | |||||
void removeParamHandle(ParamHandle* paramHandle); | void removeParamHandle(ParamHandle* paramHandle); | ||||
/** Returns the unique ParamHandle for the given paramId | /** Returns the unique ParamHandle for the given paramId | ||||
*/ | */ | ||||
ParamHandle* getParamHandle(int moduleId, int paramId); | |||||
/** Use getParamHandle(int, int) instead. | |||||
*/ | |||||
ParamHandle* getParamHandle(int64_t moduleId, int paramId); | |||||
/** Use getParamHandle(moduleId, paramId) instead. */ | |||||
DEPRECATED ParamHandle* getParamHandle(Module* module, int paramId); | DEPRECATED ParamHandle* getParamHandle(Module* module, int paramId); | ||||
/** Sets the ParamHandle IDs and module pointer. | /** Sets the ParamHandle IDs and module pointer. | ||||
If `overwrite` is true and another ParamHandle points to the same param, unsets that one and replaces it with the given handle. | If `overwrite` is true and another ParamHandle points to the same param, unsets that one and replaces it with the given handle. | ||||
*/ | */ | ||||
void updateParamHandle(ParamHandle* paramHandle, int moduleId, int paramId, bool overwrite = true); | |||||
void updateParamHandle(ParamHandle* paramHandle, int64_t moduleId, int paramId, bool overwrite = true); | |||||
json_t* toJson(); | json_t* toJson(); | ||||
void fromJson(json_t* rootJ); | void fromJson(json_t* rootJ); | ||||
@@ -50,7 +50,7 @@ struct Module { | |||||
/** Represents a message-passing channel for an adjacent module. */ | /** Represents a message-passing channel for an adjacent module. */ | ||||
struct Expander { | struct Expander { | ||||
/** ID of the expander module, or -1 if nonexistent. */ | /** ID of the expander module, or -1 if nonexistent. */ | ||||
int moduleId = -1; | |||||
int64_t moduleId = -1; | |||||
/** Pointer to the expander Module, or NULL if nonexistent. */ | /** Pointer to the expander Module, or NULL if nonexistent. */ | ||||
Module* module = NULL; | Module* module = NULL; | ||||
/** Double buffer for receiving messages from the expander module. | /** Double buffer for receiving messages from the expander module. | ||||
@@ -14,7 +14,7 @@ struct ParamHandle { | |||||
/** Do not set these directly. | /** Do not set these directly. | ||||
Use Engine ParamHandle methods. | Use Engine ParamHandle methods. | ||||
*/ | */ | ||||
int moduleId = -1; | |||||
int64_t moduleId = -1; | |||||
int paramId = 0; | int paramId = 0; | ||||
Module* module = NULL; | Module* module = NULL; | ||||
@@ -64,7 +64,7 @@ struct ComplexAction : Action { | |||||
Subclass this to create your own custom actions for your module. | Subclass this to create your own custom actions for your module. | ||||
*/ | */ | ||||
struct ModuleAction : Action { | struct ModuleAction : Action { | ||||
int moduleId; | |||||
int64_t moduleId; | |||||
}; | }; | ||||
@@ -135,10 +135,10 @@ struct ParamChange : ModuleAction { | |||||
struct CableAdd : Action { | struct CableAdd : Action { | ||||
int cableId; | |||||
int inputModuleId; | |||||
int64_t cableId; | |||||
int64_t inputModuleId; | |||||
int inputId; | int inputId; | ||||
int outputModuleId; | |||||
int64_t outputModuleId; | |||||
int outputId; | int outputId; | ||||
NVGcolor color; | NVGcolor color; | ||||
void setCable(app::CableWidget* cw); | void setCable(app::CableWidget* cw); | ||||
@@ -182,11 +182,13 @@ void RackWidget::mergeJson(json_t* rootJ) { | |||||
json_t* idJ = json_object_get(moduleJ, "id"); | json_t* idJ = json_object_get(moduleJ, "id"); | ||||
if (!idJ) | if (!idJ) | ||||
continue; | continue; | ||||
int id = json_integer_value(idJ); | |||||
int64_t id = json_integer_value(idJ); | |||||
// TODO Legacy v0.6? | // TODO Legacy v0.6? | ||||
ModuleWidget* moduleWidget = getModule(id); | ModuleWidget* moduleWidget = getModule(id); | ||||
if (!moduleWidget) | |||||
if (!moduleWidget) { | |||||
WARN("Cannot find ModuleWidget with ID %ld", id); | |||||
continue; | continue; | ||||
} | |||||
// pos | // pos | ||||
math::Vec pos = moduleWidget->box.pos.minus(moduleOffset); | math::Vec pos = moduleWidget->box.pos.minus(moduleOffset); | ||||
@@ -206,10 +208,12 @@ void RackWidget::mergeJson(json_t* rootJ) { | |||||
json_t* idJ = json_object_get(cableJ, "id"); | json_t* idJ = json_object_get(cableJ, "id"); | ||||
if (!idJ) | if (!idJ) | ||||
continue; | continue; | ||||
int id = json_integer_value(idJ); | |||||
int64_t id = json_integer_value(idJ); | |||||
CableWidget* cw = getCable(id); | CableWidget* cw = getCable(id); | ||||
if (!cw) | |||||
if (!cw) { | |||||
WARN("Cannot find CableWidget with ID %ld", id); | |||||
continue; | continue; | ||||
} | |||||
json_t* cwJ = cw->toJson(); | json_t* cwJ = cw->toJson(); | ||||
// Merge cable JSON object | // Merge cable JSON object | ||||
@@ -230,10 +234,12 @@ void RackWidget::fromJson(json_t* rootJ) { | |||||
json_t* idJ = json_object_get(moduleJ, "id"); | json_t* idJ = json_object_get(moduleJ, "id"); | ||||
if (!idJ) | if (!idJ) | ||||
continue; | continue; | ||||
int id = json_integer_value(idJ); | |||||
int64_t id = json_integer_value(idJ); | |||||
engine::Module* module = APP->engine->getModule(id); | engine::Module* module = APP->engine->getModule(id); | ||||
if (!module) | |||||
if (!module) { | |||||
WARN("Cannot find module with ID %ld", id); | |||||
continue; | continue; | ||||
} | |||||
ModuleWidget* moduleWidget = module->model->createModuleWidget(module); | ModuleWidget* moduleWidget = module->model->createModuleWidget(module); | ||||
@@ -273,10 +279,12 @@ void RackWidget::fromJson(json_t* rootJ) { | |||||
json_t* idJ = json_object_get(cableJ, "id"); | json_t* idJ = json_object_get(cableJ, "id"); | ||||
if (!idJ) | if (!idJ) | ||||
continue; | continue; | ||||
int id = json_integer_value(idJ); | |||||
int64_t id = json_integer_value(idJ); | |||||
engine::Cable* cable = APP->engine->getCable(id); | engine::Cable* cable = APP->engine->getCable(id); | ||||
if (!cable) | |||||
if (!cable) { | |||||
WARN("Cannot find cable with ID %ld", id); | |||||
continue; | continue; | ||||
} | |||||
CableWidget* cw = new CableWidget; | CableWidget* cw = new CableWidget; | ||||
// Legacy: Before v1, cable colors were not serialized. So we need to initialize the color here. | // Legacy: Before v1, cable colors were not serialized. So we need to initialize the color here. | ||||
@@ -515,7 +523,7 @@ void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) { | |||||
RackWidget_updateAdjacent(this); | RackWidget_updateAdjacent(this); | ||||
} | } | ||||
ModuleWidget* RackWidget::getModule(int moduleId) { | |||||
ModuleWidget* RackWidget::getModule(int64_t moduleId) { | |||||
for (widget::Widget* w : moduleContainer->children) { | for (widget::Widget* w : moduleContainer->children) { | ||||
ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w); | ModuleWidget* mw = dynamic_cast<ModuleWidget*>(w); | ||||
assert(mw); | assert(mw); | ||||
@@ -648,7 +656,7 @@ CableWidget* RackWidget::getTopCable(PortWidget* port) { | |||||
return NULL; | return NULL; | ||||
} | } | ||||
CableWidget* RackWidget::getCable(int cableId) { | |||||
CableWidget* RackWidget::getCable(int64_t cableId) { | |||||
for (widget::Widget* w : cableContainer->children) { | for (widget::Widget* w : cableContainer->children) { | ||||
CableWidget* cw = dynamic_cast<CableWidget*>(w); | CableWidget* cw = dynamic_cast<CableWidget*>(w); | ||||
assert(cw); | assert(cw); | ||||
@@ -225,7 +225,7 @@ struct MIDI_Map : Module { | |||||
} | } | ||||
} | } | ||||
void learnParam(int id, int moduleId, int paramId) { | |||||
void learnParam(int id, int64_t moduleId, int paramId) { | |||||
APP->engine->updateParamHandle(¶mHandles[id], moduleId, paramId, true); | APP->engine->updateParamHandle(¶mHandles[id], moduleId, paramId, true); | ||||
learnedParam = true; | learnedParam = true; | ||||
commitLearn(); | commitLearn(); | ||||
@@ -335,7 +335,7 @@ struct MIDI_MapChoice : LedDisplayChoice { | |||||
ParamWidget* touchedParam = APP->scene->rack->touchedParam; | ParamWidget* touchedParam = APP->scene->rack->touchedParam; | ||||
if (touchedParam) { | if (touchedParam) { | ||||
APP->scene->rack->touchedParam = NULL; | APP->scene->rack->touchedParam = NULL; | ||||
int moduleId = touchedParam->module->id; | |||||
int64_t moduleId = touchedParam->module->id; | |||||
int paramId = touchedParam->paramId; | int paramId = touchedParam->paramId; | ||||
module->learnParam(id, moduleId, paramId); | module->learnParam(id, moduleId, paramId); | ||||
} | } | ||||
@@ -23,7 +23,7 @@ void Cable::fromJson(json_t* rootJ) { | |||||
json_t* inputModuleIdJ = json_object_get(rootJ, "inputModuleId"); | json_t* inputModuleIdJ = json_object_get(rootJ, "inputModuleId"); | ||||
if (!inputModuleIdJ) | if (!inputModuleIdJ) | ||||
throw Exception("inputModuleId not found for cable"); | throw Exception("inputModuleId not found for cable"); | ||||
int inputModuleId = json_integer_value(inputModuleIdJ); | |||||
int64_t inputModuleId = json_integer_value(inputModuleIdJ); | |||||
inputModule = APP->engine->getModule(inputModuleId); | inputModule = APP->engine->getModule(inputModuleId); | ||||
if (!inputModule) | if (!inputModule) | ||||
throw Exception("inputModule not found for cable"); | throw Exception("inputModule not found for cable"); | ||||
@@ -38,7 +38,7 @@ void Cable::fromJson(json_t* rootJ) { | |||||
json_t* outputModuleIdJ = json_object_get(rootJ, "outputModuleId"); | json_t* outputModuleIdJ = json_object_get(rootJ, "outputModuleId"); | ||||
if (!outputModuleIdJ) | if (!outputModuleIdJ) | ||||
throw Exception("outputModuleId not found for cable"); | throw Exception("outputModuleId not found for cable"); | ||||
int outputModuleId = json_integer_value(outputModuleIdJ); | |||||
int64_t outputModuleId = json_integer_value(outputModuleIdJ); | |||||
outputModule = APP->engine->getModule(outputModuleId); | outputModule = APP->engine->getModule(outputModuleId); | ||||
if (!outputModule) | if (!outputModule) | ||||
throw Exception("outputModule not found for cable"); | throw Exception("outputModule not found for cable"); | ||||
@@ -188,11 +188,11 @@ struct Engine::Internal { | |||||
std::set<ParamHandle*> paramHandles; | std::set<ParamHandle*> paramHandles; | ||||
// moduleId | // moduleId | ||||
std::map<int, Module*> modulesCache; | |||||
std::map<int64_t, Module*> modulesCache; | |||||
// cableId | // cableId | ||||
std::map<int, Cable*> cablesCache; | |||||
std::map<int64_t, Cable*> cablesCache; | |||||
// (moduleId, paramId) | // (moduleId, paramId) | ||||
std::map<std::tuple<int, int>, ParamHandle*> paramHandlesCache; | |||||
std::map<std::tuple<int64_t, int>, ParamHandle*> paramHandlesCache; | |||||
float sampleRate = 0.f; | float sampleRate = 0.f; | ||||
float sampleTime = 0.f; | float sampleTime = 0.f; | ||||
@@ -657,21 +657,22 @@ size_t Engine::getNumModules() { | |||||
} | } | ||||
void Engine::getModuleIds(int* moduleIds, int len) { | |||||
size_t Engine::getModuleIds(int64_t* moduleIds, size_t len) { | |||||
SharedLock lock(internal->mutex); | SharedLock lock(internal->mutex); | ||||
int i = 0; | |||||
size_t i = 0; | |||||
for (Module* m : internal->modules) { | for (Module* m : internal->modules) { | ||||
if (i >= len) | if (i >= len) | ||||
break; | break; | ||||
moduleIds[i] = m->id; | moduleIds[i] = m->id; | ||||
i++; | i++; | ||||
} | } | ||||
return i; | |||||
} | } | ||||
std::vector<int> Engine::getModuleIds() { | |||||
std::vector<int64_t> Engine::getModuleIds() { | |||||
SharedLock lock(internal->mutex); | SharedLock lock(internal->mutex); | ||||
std::vector<int> moduleIds; | |||||
std::vector<int64_t> moduleIds; | |||||
moduleIds.reserve(internal->modules.size()); | moduleIds.reserve(internal->modules.size()); | ||||
for (Module* m : internal->modules) { | for (Module* m : internal->modules) { | ||||
moduleIds.push_back(m->id); | moduleIds.push_back(m->id); | ||||
@@ -748,7 +749,7 @@ void Engine::removeModule(Module* module) { | |||||
} | } | ||||
Module* Engine::getModule(int moduleId) { | |||||
Module* Engine::getModule(int64_t moduleId) { | |||||
SharedLock lock(internal->mutex); | SharedLock lock(internal->mutex); | ||||
auto it = internal->modulesCache.find(moduleId); | auto it = internal->modulesCache.find(moduleId); | ||||
if (it == internal->modulesCache.end()) | if (it == internal->modulesCache.end()) | ||||
@@ -812,6 +813,35 @@ void Engine::moduleFromJson(Module* module, json_t* rootJ) { | |||||
} | } | ||||
size_t Engine::getNumCables() { | |||||
return internal->cables.size(); | |||||
} | |||||
size_t Engine::getCableIds(int64_t* cableIds, size_t len) { | |||||
SharedLock lock(internal->mutex); | |||||
size_t i = 0; | |||||
for (Cable* c : internal->cables) { | |||||
if (i >= len) | |||||
break; | |||||
cableIds[i] = c->id; | |||||
i++; | |||||
} | |||||
return i; | |||||
} | |||||
std::vector<int64_t> Engine::getCableIds() { | |||||
SharedLock lock(internal->mutex); | |||||
std::vector<int64_t> cableIds; | |||||
cableIds.reserve(internal->cables.size()); | |||||
for (Cable* c : internal->cables) { | |||||
cableIds.push_back(c->id); | |||||
} | |||||
return cableIds; | |||||
} | |||||
void Engine::addCable(Cable* cable) { | void Engine::addCable(Cable* cable) { | ||||
ExclusiveSharedLock lock(internal->mutex); | ExclusiveSharedLock lock(internal->mutex); | ||||
assert(cable); | assert(cable); | ||||
@@ -893,7 +923,7 @@ void Engine::removeCable(Cable* cable) { | |||||
} | } | ||||
Cable* Engine::getCable(int cableId) { | |||||
Cable* Engine::getCable(int64_t cableId) { | |||||
SharedLock lock(internal->mutex); | SharedLock lock(internal->mutex); | ||||
auto it = internal->cablesCache.find(cableId); | auto it = internal->cablesCache.find(cableId); | ||||
if (it == internal->cablesCache.end()) | if (it == internal->cablesCache.end()) | ||||
@@ -965,7 +995,7 @@ void Engine::removeParamHandle(ParamHandle* paramHandle) { | |||||
} | } | ||||
ParamHandle* Engine::getParamHandle(int moduleId, int paramId) { | |||||
ParamHandle* Engine::getParamHandle(int64_t moduleId, int paramId) { | |||||
SharedLock lock(internal->mutex); | SharedLock lock(internal->mutex); | ||||
auto it = internal->paramHandlesCache.find(std::make_tuple(moduleId, paramId)); | auto it = internal->paramHandlesCache.find(std::make_tuple(moduleId, paramId)); | ||||
if (it == internal->paramHandlesCache.end()) | if (it == internal->paramHandlesCache.end()) | ||||
@@ -979,7 +1009,7 @@ ParamHandle* Engine::getParamHandle(Module* module, int paramId) { | |||||
} | } | ||||
void Engine::updateParamHandle(ParamHandle* paramHandle, int moduleId, int paramId, bool overwrite) { | |||||
void Engine::updateParamHandle(ParamHandle* paramHandle, int64_t moduleId, int paramId, bool overwrite) { | |||||
SharedLock lock(internal->mutex); | SharedLock lock(internal->mutex); | ||||
// Check that it exists | // Check that it exists | ||||
auto it = internal->paramHandles.find(paramHandle); | auto it = internal->paramHandles.find(paramHandle); | ||||