Audio plugin host https://kx.studio/carla
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.

CarlaJsfxUtils.hpp 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Carla JSFX utils
  3. * Copyright (C) 2021 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_JSFX_UTILS_HPP_INCLUDED
  18. #define CARLA_JSFX_UTILS_HPP_INCLUDED
  19. #include "CarlaUtils.hpp"
  20. #include "CarlaString.hpp"
  21. #include "CarlaBase64Utils.hpp"
  22. #include "water/files/File.h"
  23. #include "water/xml/XmlElement.h"
  24. #include "water/xml/XmlDocument.h"
  25. #include "water/streams/MemoryInputStream.h"
  26. #include "water/streams/MemoryOutputStream.h"
  27. #pragma GCC diagnostic push
  28. #pragma GCC diagnostic ignored "-Wunused-parameter"
  29. #pragma GCC diagnostic ignored "-Wignored-attributes"
  30. #include "jsusfx.h"
  31. #include "jsusfx_file.h"
  32. #include "jsusfx_gfx.h"
  33. #include "jsusfx_serialize.h"
  34. #pragma GCC diagnostic pop
  35. #include <memory>
  36. class CarlaJsusFx : public JsusFx
  37. {
  38. public:
  39. explicit CarlaJsusFx(JsusFxPathLibrary &pathLibrary)
  40. : JsusFx(pathLibrary)
  41. {
  42. }
  43. void setQuiet(bool quiet)
  44. {
  45. fQuiet = quiet;
  46. }
  47. void displayMsg(const char* fmt, ...) override
  48. {
  49. if (!fQuiet)
  50. {
  51. char msgBuf[256];
  52. ::va_list args;
  53. ::va_start(args, fmt);
  54. std::vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
  55. msgBuf[255] = 0;
  56. ::va_end(args);
  57. carla_stdout("%s", msgBuf);
  58. }
  59. }
  60. void displayError(const char* fmt, ...) override
  61. {
  62. if (!fQuiet)
  63. {
  64. char msgBuf[256];
  65. ::va_list args;
  66. ::va_start(args, fmt);
  67. std::vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
  68. msgBuf[255] = 0;
  69. ::va_end(args);
  70. carla_stderr("%s", msgBuf);
  71. }
  72. }
  73. private:
  74. bool fQuiet = false;
  75. };
  76. // -------------------------------------------------------------------------------------------------------------------
  77. class CarlaJsusFxPathLibrary : public JsusFxPathLibrary_Basic
  78. {
  79. public:
  80. explicit CarlaJsusFxPathLibrary(const water::File &file)
  81. : JsusFxPathLibrary_Basic(determineDataRoot(file).c_str())
  82. {
  83. }
  84. private:
  85. static std::string determineDataRoot(const water::File &file)
  86. {
  87. return file.getParentDirectory().getFullPathName().toRawUTF8();
  88. }
  89. };
  90. // -------------------------------------------------------------------------------------------------------------------
  91. class CarlaJsusFxFileAPI : public JsusFxFileAPI_Basic
  92. {
  93. public:
  94. };
  95. // -------------------------------------------------------------------------------------------------------------------
  96. class CarlaJsusFxSerializer : public JsusFxSerializer_Basic
  97. {
  98. public:
  99. explicit CarlaJsusFxSerializer(JsusFxSerializationData& data)
  100. : JsusFxSerializer_Basic(data)
  101. {
  102. }
  103. static water::String convertDataToString(const JsusFxSerializationData& data)
  104. {
  105. water::XmlElement root("JSFXState");
  106. std::size_t numSliders = data.sliders.size();
  107. for (std::size_t i = 0; i < numSliders; ++i)
  108. {
  109. water::XmlElement *slider = new water::XmlElement("Slider");
  110. slider->setAttribute("index", data.sliders[i].index);
  111. slider->setAttribute("value", data.sliders[i].value);
  112. root.addChildElement(slider);
  113. }
  114. std::size_t numVars = data.vars.size();
  115. if (numVars > 0)
  116. {
  117. water::MemoryOutputStream blob;
  118. for (std::size_t i = 0; i < numVars; ++i)
  119. {
  120. blob.writeFloat(data.vars[i]);
  121. }
  122. const CarlaString base64 = CarlaString::asBase64(blob.getData(), blob.getDataSize());
  123. water::XmlElement *var = new water::XmlElement("Serialization");
  124. var->addTextElement(base64.buffer());
  125. root.addChildElement(var);
  126. }
  127. water::MemoryOutputStream stream;
  128. root.writeToStream(stream, water::StringRef(), true);
  129. return stream.toUTF8();
  130. }
  131. static bool convertStringToData(const water::String& string, JsusFxSerializationData& data)
  132. {
  133. std::unique_ptr<water::XmlElement> root(water::XmlDocument::parse(string));
  134. CARLA_SAFE_ASSERT_RETURN(root != nullptr, false);
  135. CARLA_SAFE_ASSERT_RETURN(root->getTagName() == "JSFXState", false);
  136. data = JsusFxSerializationData();
  137. int numChildren = root->getNumChildElements();
  138. for (int i = 0; i < numChildren; ++i)
  139. {
  140. water::XmlElement* child = root->getChildElement(i);
  141. CARLA_SAFE_ASSERT_CONTINUE(child != nullptr);
  142. if (child->getTagName() == "Slider")
  143. {
  144. CARLA_SAFE_ASSERT_CONTINUE(child->hasAttribute("index"));
  145. CARLA_SAFE_ASSERT_CONTINUE(child->hasAttribute("value"));
  146. JsusFxSerializationData::Slider slider;
  147. slider.index = child->getIntAttribute("index");
  148. slider.value = child->getDoubleAttribute("value");
  149. data.sliders.push_back(slider);
  150. }
  151. else if (child->getTagName() == "Serialization")
  152. {
  153. std::vector<uint8_t> chunk = carla_getChunkFromBase64String(child->getAllSubText().toRawUTF8());
  154. water::MemoryInputStream blob(chunk.data(), chunk.size(), false);
  155. size_t numVars = chunk.size() / sizeof(float);
  156. data.vars.resize(numVars);
  157. for (std::size_t i = 0; i < numVars; ++i)
  158. {
  159. data.vars[i] = blob.readFloat();
  160. }
  161. }
  162. else
  163. {
  164. CARLA_SAFE_ASSERT_CONTINUE(false);
  165. }
  166. }
  167. return true;
  168. }
  169. };
  170. // -------------------------------------------------------------------------------------------------------------------
  171. #endif // CARLA_JSFX_UTILS_HPP_INCLUDED