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.

150 lines
3.8KB

  1. #include <plugin/Plugin.hpp>
  2. #include <plugin/Model.hpp>
  3. #include <plugin.hpp>
  4. #include <string.hpp>
  5. #include <app/common.hpp>
  6. namespace rack {
  7. namespace plugin {
  8. Plugin::~Plugin() {
  9. for (Model* model : models) {
  10. delete model;
  11. }
  12. }
  13. void Plugin::addModel(Model* model) {
  14. // Check that the model is not added to a plugin already
  15. assert(!model->plugin);
  16. model->plugin = this;
  17. models.push_back(model);
  18. }
  19. Model* Plugin::getModel(std::string slug) {
  20. for (Model* model : models) {
  21. if (model->slug == slug) {
  22. return model;
  23. }
  24. }
  25. return NULL;
  26. }
  27. void Plugin::fromJson(json_t* rootJ) {
  28. // Slug
  29. json_t* slugJ = json_object_get(rootJ, "slug");
  30. if (slugJ)
  31. slug = json_string_value(slugJ);
  32. if (slug == "")
  33. throw UserException("No plugin slug");
  34. if (!isSlugValid(slug))
  35. throw UserException(string::f("Plugin slug \"%s\" is invalid", slug.c_str()));
  36. // Version
  37. json_t* versionJ = json_object_get(rootJ, "version");
  38. if (versionJ)
  39. version = json_string_value(versionJ);
  40. if (!string::startsWith(version, app::ABI_VERSION + "."))
  41. throw UserException(string::f("Plugin version %s does not match Rack ABI version %s", version.c_str(), app::ABI_VERSION.c_str()));
  42. if (version == "")
  43. throw UserException("No plugin version");
  44. // Name
  45. json_t* nameJ = json_object_get(rootJ, "name");
  46. if (nameJ)
  47. name = json_string_value(nameJ);
  48. if (name == "")
  49. throw UserException("No plugin name");
  50. // Brand
  51. json_t* brandJ = json_object_get(rootJ, "brand");
  52. if (brandJ)
  53. brand = json_string_value(brandJ);
  54. // Use name for brand name by default
  55. if (brand == "")
  56. brand = name;
  57. json_t* authorJ = json_object_get(rootJ, "author");
  58. if (authorJ)
  59. author = json_string_value(authorJ);
  60. json_t* licenseJ = json_object_get(rootJ, "license");
  61. if (licenseJ)
  62. license = json_string_value(licenseJ);
  63. json_t* authorEmailJ = json_object_get(rootJ, "authorEmail");
  64. if (authorEmailJ)
  65. authorEmail = json_string_value(authorEmailJ);
  66. json_t* pluginUrlJ = json_object_get(rootJ, "pluginUrl");
  67. if (pluginUrlJ)
  68. pluginUrl = json_string_value(pluginUrlJ);
  69. json_t* authorUrlJ = json_object_get(rootJ, "authorUrl");
  70. if (authorUrlJ)
  71. authorUrl = json_string_value(authorUrlJ);
  72. json_t* manualUrlJ = json_object_get(rootJ, "manualUrl");
  73. if (manualUrlJ)
  74. manualUrl = json_string_value(manualUrlJ);
  75. json_t* sourceUrlJ = json_object_get(rootJ, "sourceUrl");
  76. if (sourceUrlJ)
  77. sourceUrl = json_string_value(sourceUrlJ);
  78. json_t* donateUrlJ = json_object_get(rootJ, "donateUrl");
  79. if (donateUrlJ)
  80. donateUrl = json_string_value(donateUrlJ);
  81. json_t* modulesJ = json_object_get(rootJ, "modules");
  82. if (modulesJ) {
  83. size_t moduleId;
  84. json_t* moduleJ;
  85. json_array_foreach(modulesJ, moduleId, moduleJ) {
  86. // Check if module is disabled
  87. json_t* disabledJ = json_object_get(moduleJ, "disabled");
  88. if (disabledJ) {
  89. if (json_boolean_value(disabledJ))
  90. continue;
  91. }
  92. // Get model slug
  93. json_t* modelSlugJ = json_object_get(moduleJ, "slug");
  94. if (!modelSlugJ) {
  95. throw UserException(string::f("No slug found for module entry %d", moduleId));
  96. }
  97. std::string modelSlug = json_string_value(modelSlugJ);
  98. // Check model slug
  99. if (!isSlugValid(modelSlug)) {
  100. throw UserException(string::f("Module slug \"%s\" is invalid", modelSlug.c_str()));
  101. }
  102. // Get model
  103. Model* model = getModel(modelSlug);
  104. if (!model) {
  105. throw UserException(string::f("Manifest contains module %s but it is not defined in the plugin", modelSlug.c_str()));
  106. }
  107. model->fromJson(moduleJ);
  108. }
  109. }
  110. // Remove models without names
  111. // This is a hacky way of matching JSON models with C++ models.
  112. for (auto it = models.begin(); it != models.end();) {
  113. Model* model = *it;
  114. if (model->name == "") {
  115. it = models.erase(it);
  116. delete model;
  117. continue;
  118. }
  119. it++;
  120. }
  121. }
  122. } // namespace plugin
  123. } // namespace rack