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.

327 lines
9.6KB

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