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.

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