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.

366 lines
10KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2014 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. #include "CarlaEngineUtils.hpp"
  18. #include "CarlaEngineInternal.hpp"
  19. #include "CarlaString.hpp"
  20. #include "CarlaStringList.hpp"
  21. CARLA_BACKEND_START_NAMESPACE
  22. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  23. // -----------------------------------------------------------------------
  24. // Carla Engine Meta CV port
  25. class CarlaEngineCVSourcePorts2 : public CarlaEngineCVSourcePorts
  26. {
  27. public:
  28. CarlaEngineCVSourcePorts2()
  29. : CarlaEngineCVSourcePorts()
  30. {}
  31. ~CarlaEngineCVSourcePorts2() override {}
  32. void setGraphAndPlugin(PatchbayGraph* const graph, CarlaPlugin* const plugin) noexcept
  33. {
  34. pData->graph = graph;
  35. pData->plugin = plugin;
  36. }
  37. };
  38. #endif
  39. // -----------------------------------------------------------------------
  40. // Carla Engine client (Abstract)
  41. struct CarlaEngineClient::ProtectedData {
  42. const CarlaEngine& engine;
  43. bool active;
  44. uint32_t latency;
  45. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  46. CarlaEngineCVSourcePorts2 cvSourcePorts;
  47. EngineInternalGraph& egraph;
  48. CarlaPlugin* const plugin;
  49. #endif
  50. CarlaStringList audioInList;
  51. CarlaStringList audioOutList;
  52. CarlaStringList cvInList;
  53. CarlaStringList cvOutList;
  54. CarlaStringList eventInList;
  55. CarlaStringList eventOutList;
  56. ProtectedData(const CarlaEngine& eng, EngineInternalGraph& eg, CarlaPlugin* const p) noexcept
  57. : engine(eng),
  58. active(false),
  59. latency(0),
  60. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  61. cvSourcePorts(),
  62. egraph(eg),
  63. plugin(p),
  64. #endif
  65. audioInList(),
  66. audioOutList(),
  67. cvInList(),
  68. cvOutList(),
  69. eventInList(),
  70. eventOutList() {}
  71. #ifdef CARLA_PROPER_CPP11_SUPPORT
  72. ProtectedData() = delete;
  73. CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData)
  74. #endif
  75. };
  76. CarlaEngineClient2::CarlaEngineClient2(const CarlaEngine& engine, EngineInternalGraph& egraph, CarlaPlugin* const plugin)
  77. : CarlaEngineClient(new ProtectedData(engine, egraph, plugin))
  78. {
  79. }
  80. CarlaEngineClient2::~CarlaEngineClient2()
  81. {
  82. }
  83. PatchbayGraph* CarlaEngineClient2::getPatchbayGraph() const noexcept
  84. {
  85. return pData->egraph.getPatchbayGraph();
  86. }
  87. CarlaPlugin* CarlaEngineClient2::getPlugin() const noexcept
  88. {
  89. return pData->plugin;
  90. }
  91. CarlaEngineClient::CarlaEngineClient(ProtectedData* const p)
  92. : pData(p)
  93. {
  94. carla_debug("CarlaEngineClient::CarlaEngineClient()");
  95. }
  96. CarlaEngineClient::~CarlaEngineClient() noexcept
  97. {
  98. CARLA_SAFE_ASSERT(! pData->active);
  99. carla_debug("CarlaEngineClient::~CarlaEngineClient()");
  100. delete pData;
  101. }
  102. void CarlaEngineClient::activate() noexcept
  103. {
  104. CARLA_SAFE_ASSERT(! pData->active);
  105. carla_debug("CarlaEngineClient::activate()");
  106. pData->active = true;
  107. }
  108. void CarlaEngineClient::deactivate() noexcept
  109. {
  110. CARLA_SAFE_ASSERT(pData->active);
  111. carla_debug("CarlaEngineClient::deactivate()");
  112. pData->active = false;
  113. }
  114. bool CarlaEngineClient::isActive() const noexcept
  115. {
  116. return pData->active;
  117. }
  118. bool CarlaEngineClient::isOk() const noexcept
  119. {
  120. return true;
  121. }
  122. uint32_t CarlaEngineClient::getLatency() const noexcept
  123. {
  124. return pData->latency;
  125. }
  126. void CarlaEngineClient::setLatency(const uint32_t samples) noexcept
  127. {
  128. pData->latency = samples;
  129. }
  130. CarlaEnginePort* CarlaEngineClient::addPort(const EnginePortType portType, const char* const name, const bool isInput, const uint32_t indexOffset)
  131. {
  132. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
  133. carla_debug("CarlaEngineClient::addPort(%i:%s, \"%s\", %s)", portType, EnginePortType2Str(portType), name, bool2str(isInput));
  134. switch (portType)
  135. {
  136. case kEnginePortTypeNull:
  137. break;
  138. case kEnginePortTypeAudio:
  139. _addAudioPortName(isInput, name);
  140. return new CarlaEngineAudioPort(*this, isInput, indexOffset);
  141. case kEnginePortTypeCV:
  142. _addCVPortName(isInput, name);
  143. return new CarlaEngineCVPort(*this, isInput, indexOffset);
  144. case kEnginePortTypeEvent:
  145. _addEventPortName(isInput, name);
  146. return new CarlaEngineEventPort(*this, isInput, indexOffset);
  147. }
  148. carla_stderr("CarlaEngineClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput));
  149. return nullptr;
  150. }
  151. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  152. CarlaEngineCVSourcePorts* CarlaEngineClient::createCVSourcePorts()
  153. {
  154. pData->cvSourcePorts.setGraphAndPlugin(pData->egraph.getPatchbayGraph(), pData->plugin);
  155. return &pData->cvSourcePorts;
  156. }
  157. #endif
  158. const CarlaEngine& CarlaEngineClient::getEngine() const noexcept
  159. {
  160. return pData->engine;
  161. }
  162. EngineProcessMode CarlaEngineClient::getProcessMode() const noexcept
  163. {
  164. return pData->engine.getProccessMode();
  165. }
  166. uint CarlaEngineClient::getPortCount(const EnginePortType portType, const bool isInput) const noexcept
  167. {
  168. size_t ret = 0;
  169. switch (portType)
  170. {
  171. case kEnginePortTypeNull:
  172. break;
  173. case kEnginePortTypeAudio:
  174. ret = isInput ? pData->audioInList.count() : pData->audioOutList.count();
  175. break;
  176. case kEnginePortTypeCV:
  177. ret = isInput ? pData->cvInList.count() : pData->cvOutList.count();
  178. break;
  179. case kEnginePortTypeEvent:
  180. ret = isInput ? pData->eventInList.count() : pData->eventOutList.count();
  181. break;
  182. }
  183. return static_cast<uint>(ret);
  184. }
  185. const char* CarlaEngineClient::getAudioPortName(const bool isInput, const uint index) const noexcept
  186. {
  187. CarlaStringList& portList(isInput ? pData->audioInList : pData->audioOutList);
  188. CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr);
  189. return portList.getAt(index);
  190. }
  191. const char* CarlaEngineClient::getCVPortName(const bool isInput, const uint index) const noexcept
  192. {
  193. CarlaStringList& portList(isInput ? pData->cvInList : pData->cvOutList);
  194. CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr);
  195. return portList.getAt(index);
  196. }
  197. const char* CarlaEngineClient::getEventPortName(const bool isInput, const uint index) const noexcept
  198. {
  199. CarlaStringList& portList(isInput ? pData->eventInList : pData->eventOutList);
  200. CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr);
  201. return portList.getAt(index);
  202. }
  203. void CarlaEngineClient::_addAudioPortName(const bool isInput, const char* const name)
  204. {
  205. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
  206. CarlaStringList& portList(isInput ? pData->audioInList : pData->audioOutList);
  207. portList.append(name);
  208. }
  209. void CarlaEngineClient::_addCVPortName(const bool isInput, const char* const name)
  210. {
  211. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
  212. CarlaStringList& portList(isInput ? pData->cvInList : pData->cvOutList);
  213. portList.append(name);
  214. }
  215. void CarlaEngineClient::_addEventPortName(const bool isInput, const char* const name)
  216. {
  217. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
  218. CarlaStringList& portList(isInput ? pData->eventInList : pData->eventOutList);
  219. portList.append(name);
  220. }
  221. static void getUniquePortName(CarlaString& sname, const CarlaStringList& list)
  222. {
  223. for (CarlaStringList::Itenerator it = list.begin2(); it.valid(); it.next())
  224. {
  225. const char* const portName(it.getValue(nullptr));
  226. CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');
  227. // Check if unique name doesn't exist
  228. if (sname != portName)
  229. continue;
  230. // Check if string has already been modified
  231. {
  232. const std::size_t len(sname.length());
  233. // 1 digit, ex: " (2)"
  234. if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')')
  235. {
  236. const int number = sname[len-2] - '0';
  237. if (number == 9)
  238. {
  239. // next number is 10, 2 digits
  240. sname.truncate(len-4);
  241. sname += " (10)";
  242. //sname.replace(" (9)", " (10)");
  243. }
  244. else
  245. sname[len-2] = char('0' + number + 1);
  246. continue;
  247. }
  248. // 2 digits, ex: " (11)"
  249. if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')')
  250. {
  251. char n2 = sname[len-2];
  252. char n3 = sname[len-3];
  253. if (n2 == '9')
  254. {
  255. n2 = '0';
  256. n3 = static_cast<char>(n3 + 1);
  257. }
  258. else
  259. n2 = static_cast<char>(n2 + 1);
  260. sname[len-2] = n2;
  261. sname[len-3] = n3;
  262. continue;
  263. }
  264. }
  265. // Modify string if not
  266. sname += " (2)";
  267. }
  268. }
  269. const char* CarlaEngineClient::_getUniquePortName(const char* const name)
  270. {
  271. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
  272. CarlaString sname;
  273. sname = name;
  274. getUniquePortName(sname, pData->audioInList);
  275. getUniquePortName(sname, pData->audioOutList);
  276. getUniquePortName(sname, pData->cvInList);
  277. getUniquePortName(sname, pData->cvOutList);
  278. getUniquePortName(sname, pData->eventInList);
  279. getUniquePortName(sname, pData->eventOutList);
  280. return sname.dup();
  281. }
  282. void CarlaEngineClient::_clearPorts()
  283. {
  284. pData->audioInList.clear();
  285. pData->audioOutList.clear();
  286. pData->cvInList.clear();
  287. pData->cvOutList.clear();
  288. pData->eventInList.clear();
  289. pData->eventOutList.clear();
  290. }
  291. // void* CarlaEngineClient::_getNode() const noexcept
  292. // {
  293. // return pData->node;
  294. // }
  295. // -----------------------------------------------------------------------
  296. CARLA_BACKEND_END_NAMESPACE