You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
4.7KB

  1. #include <engine/Module.hpp>
  2. #include <plugin.hpp>
  3. namespace rack {
  4. namespace engine {
  5. Module::Module() {
  6. }
  7. Module::~Module() {
  8. for (ParamQuantity* paramQuantity : paramQuantities) {
  9. if (paramQuantity)
  10. delete paramQuantity;
  11. }
  12. }
  13. void Module::config(int numParams, int numInputs, int numOutputs, int numLights) {
  14. // This method should only be called once.
  15. assert(params.empty() && inputs.empty() && outputs.empty() && lights.empty() && paramQuantities.empty());
  16. params.resize(numParams);
  17. inputs.resize(numInputs);
  18. outputs.resize(numOutputs);
  19. lights.resize(numLights);
  20. paramQuantities.resize(numParams);
  21. // Initialize paramQuantities
  22. for (int i = 0; i < numParams; i++) {
  23. configParam(i, 0.f, 1.f, 0.f);
  24. }
  25. }
  26. json_t* Module::toJson() {
  27. json_t* rootJ = json_object();
  28. // id
  29. json_object_set_new(rootJ, "id", json_integer(id));
  30. // plugin
  31. json_object_set_new(rootJ, "plugin", json_string(model->plugin->slug.c_str()));
  32. // version
  33. json_object_set_new(rootJ, "version", json_string(model->plugin->version.c_str()));
  34. // model
  35. json_object_set_new(rootJ, "model", json_string(model->slug.c_str()));
  36. // params
  37. json_t* paramsJ = json_array();
  38. for (size_t paramId = 0; paramId < params.size(); paramId++) {
  39. // Don't serialize unbounded Params
  40. if (!paramQuantities[paramId]->isBounded())
  41. continue;
  42. json_t* paramJ = json_object();
  43. json_object_set_new(paramJ, "id", json_integer(paramId));
  44. float value = params[paramId].getValue();
  45. json_object_set_new(paramJ, "value", json_real(value));
  46. json_array_append(paramsJ, paramJ);
  47. }
  48. json_object_set_new(rootJ, "params", paramsJ);
  49. // bypass
  50. if (bypass)
  51. json_object_set_new(rootJ, "bypass", json_boolean(bypass));
  52. // leftModuleId
  53. if (leftExpander.moduleId >= 0)
  54. json_object_set_new(rootJ, "leftModuleId", json_integer(leftExpander.moduleId));
  55. // rightModuleId
  56. if (rightExpander.moduleId >= 0)
  57. json_object_set_new(rootJ, "rightModuleId", json_integer(rightExpander.moduleId));
  58. // data
  59. json_t* dataJ = dataToJson();
  60. if (dataJ) {
  61. json_object_set_new(rootJ, "data", dataJ);
  62. }
  63. return rootJ;
  64. }
  65. void Module::fromJson(json_t* rootJ) {
  66. // Check if plugin and model are incorrect
  67. json_t* pluginJ = json_object_get(rootJ, "plugin");
  68. std::string pluginSlug;
  69. if (pluginJ) {
  70. pluginSlug = json_string_value(pluginJ);
  71. pluginSlug = plugin::normalizeSlug(pluginSlug);
  72. if (pluginSlug != model->plugin->slug) {
  73. WARN("Plugin %s does not match Module's plugin %s.", pluginSlug.c_str(), model->plugin->slug.c_str());
  74. return;
  75. }
  76. }
  77. json_t* modelJ = json_object_get(rootJ, "model");
  78. std::string modelSlug;
  79. if (modelJ) {
  80. modelSlug = json_string_value(modelJ);
  81. modelSlug = plugin::normalizeSlug(modelSlug);
  82. if (modelSlug != model->slug) {
  83. WARN("Model %s does not match Module's model %s.", modelSlug.c_str(), model->slug.c_str());
  84. return;
  85. }
  86. }
  87. // Check plugin version
  88. json_t* versionJ = json_object_get(rootJ, "version");
  89. if (versionJ) {
  90. std::string version = json_string_value(versionJ);
  91. if (version != model->plugin->version) {
  92. INFO("Patch created with %s v%s, currently using v%s.", pluginSlug.c_str(), version.c_str(), model->plugin->version.c_str());
  93. }
  94. }
  95. // Only set ID if unset
  96. if (id < 0) {
  97. // id
  98. json_t* idJ = json_object_get(rootJ, "id");
  99. if (idJ)
  100. id = json_integer_value(idJ);
  101. }
  102. // params
  103. json_t* paramsJ = json_object_get(rootJ, "params");
  104. size_t i;
  105. json_t* paramJ;
  106. json_array_foreach(paramsJ, i, paramJ) {
  107. // Get paramId
  108. json_t* paramIdJ = json_object_get(paramJ, "id");
  109. // Legacy v0.6 to <v1
  110. if (!paramIdJ)
  111. paramIdJ = json_object_get(paramJ, "paramId");
  112. size_t paramId;
  113. if (paramIdJ)
  114. paramId = json_integer_value(paramIdJ);
  115. // Use index if all else fails
  116. else
  117. paramId = i;
  118. // Check ID bounds
  119. if (paramId >= params.size())
  120. continue;
  121. // Check that the Param is bounded
  122. if (!paramQuantities[paramId]->isBounded())
  123. continue;
  124. json_t* valueJ = json_object_get(paramJ, "value");
  125. if (valueJ)
  126. params[paramId].setValue(json_number_value(valueJ));
  127. }
  128. // bypass
  129. json_t* bypassJ = json_object_get(rootJ, "bypass");
  130. if (bypassJ)
  131. bypass = json_boolean_value(bypassJ);
  132. // These do not need to be deserialized, since the module positions will set them correctly when added to the rack.
  133. // // leftModuleId
  134. // json_t *leftModuleIdJ = json_object_get(rootJ, "leftModuleId");
  135. // if (leftModuleIdJ)
  136. // leftExpander.moduleId = json_integer_value(leftModuleIdJ);
  137. // // rightModuleId
  138. // json_t *rightModuleIdJ = json_object_get(rootJ, "rightModuleId");
  139. // if (rightModuleIdJ)
  140. // rightExpander.moduleId = json_integer_value(rightModuleIdJ);
  141. // data
  142. json_t* dataJ = json_object_get(rootJ, "data");
  143. if (dataJ)
  144. dataFromJson(dataJ);
  145. }
  146. } // namespace engine
  147. } // namespace rack