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.

CarlaEngineClient.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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,
  74. EngineInternalGraph& eg,
  75. const CarlaPluginPtr p) noexcept
  76. #else
  77. CarlaEngineClient::ProtectedData::ProtectedData(const CarlaEngine& eng) noexcept
  78. #endif
  79. : engine(eng),
  80. active(false),
  81. latency(0),
  82. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  83. cvSourcePorts(),
  84. egraph(eg),
  85. plugin(p),
  86. #endif
  87. audioInList(),
  88. audioOutList(),
  89. cvInList(),
  90. cvOutList(),
  91. eventInList(),
  92. eventOutList() {}
  93. CarlaEngineClient::ProtectedData::~ProtectedData()
  94. {
  95. carla_debug("CarlaEngineClient::ProtectedData::~ProtectedData()");
  96. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  97. CARLA_SAFE_ASSERT(plugin.get() == nullptr);
  98. #endif
  99. }
  100. void CarlaEngineClient::ProtectedData::addAudioPortName(const bool isInput, const char* const name)
  101. {
  102. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
  103. CarlaStringList& portList(isInput ? audioInList : audioOutList);
  104. portList.append(name);
  105. }
  106. void CarlaEngineClient::ProtectedData::addCVPortName(const bool isInput, const char* const name)
  107. {
  108. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
  109. CarlaStringList& portList(isInput ? cvInList : cvOutList);
  110. portList.append(name);
  111. }
  112. void CarlaEngineClient::ProtectedData::addEventPortName(const bool isInput, const char* const name)
  113. {
  114. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
  115. CarlaStringList& portList(isInput ? eventInList : eventOutList);
  116. portList.append(name);
  117. }
  118. const char* CarlaEngineClient::ProtectedData::getUniquePortName(const char* const name)
  119. {
  120. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
  121. CarlaString sname;
  122. sname = name;
  123. _getUniquePortName(sname, audioInList);
  124. _getUniquePortName(sname, audioOutList);
  125. _getUniquePortName(sname, cvInList);
  126. _getUniquePortName(sname, cvOutList);
  127. _getUniquePortName(sname, eventInList);
  128. _getUniquePortName(sname, eventOutList);
  129. return sname.dup();
  130. }
  131. void CarlaEngineClient::ProtectedData::clearPorts()
  132. {
  133. audioInList.clear();
  134. audioOutList.clear();
  135. cvInList.clear();
  136. cvOutList.clear();
  137. eventInList.clear();
  138. eventOutList.clear();
  139. }
  140. // -----------------------------------------------------------------------
  141. CarlaEngineClient::CarlaEngineClient(ProtectedData* const p)
  142. : pData(p)
  143. {
  144. carla_debug("CarlaEngineClient::CarlaEngineClient()");
  145. }
  146. CarlaEngineClient::~CarlaEngineClient() noexcept
  147. {
  148. carla_debug("CarlaEngineClient::~CarlaEngineClient()");
  149. }
  150. void CarlaEngineClient::activate() noexcept
  151. {
  152. CARLA_SAFE_ASSERT(! pData->active);
  153. carla_debug("CarlaEngineClient::activate()");
  154. pData->active = true;
  155. }
  156. void CarlaEngineClient::deactivate(const bool willClose) noexcept
  157. {
  158. CARLA_SAFE_ASSERT(pData->active || willClose);
  159. carla_debug("CarlaEngineClient::deactivate(%s)", bool2str(willClose));
  160. pData->active = false;
  161. if (willClose)
  162. {
  163. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  164. pData->cvSourcePorts.resetGraphAndPlugin();
  165. pData->plugin.reset();
  166. #endif
  167. }
  168. }
  169. bool CarlaEngineClient::isActive() const noexcept
  170. {
  171. return pData->active;
  172. }
  173. bool CarlaEngineClient::isOk() const noexcept
  174. {
  175. return true;
  176. }
  177. uint32_t CarlaEngineClient::getLatency() const noexcept
  178. {
  179. return pData->latency;
  180. }
  181. void CarlaEngineClient::setLatency(const uint32_t samples) noexcept
  182. {
  183. pData->latency = samples;
  184. }
  185. CarlaEnginePort* CarlaEngineClient::addPort(const EnginePortType portType, const char* const name, const bool isInput, const uint32_t indexOffset)
  186. {
  187. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
  188. carla_debug("CarlaEngineClient::addPort(%i:%s, \"%s\", %s, %u)", portType, EnginePortType2Str(portType), name, bool2str(isInput), indexOffset);
  189. switch (portType)
  190. {
  191. case kEnginePortTypeNull:
  192. break;
  193. case kEnginePortTypeAudio:
  194. pData->addAudioPortName(isInput, name);
  195. return new CarlaEngineAudioPort(*this, isInput, indexOffset);
  196. case kEnginePortTypeCV:
  197. pData->addCVPortName(isInput, name);
  198. return new CarlaEngineCVPort(*this, isInput, indexOffset);
  199. case kEnginePortTypeEvent:
  200. pData->addEventPortName(isInput, name);
  201. return new CarlaEngineEventPort(*this, isInput, indexOffset);
  202. }
  203. carla_stderr("CarlaEngineClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput));
  204. return nullptr;
  205. }
  206. bool CarlaEngineClient::removePort(const EnginePortType portType, const char* const name, const bool isInput)
  207. {
  208. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', false);
  209. carla_debug("CarlaEngineClient::removePort(%i:%s, \"%s\", %s)", portType, EnginePortType2Str(portType), name, bool2str(isInput));
  210. switch (portType)
  211. {
  212. case kEnginePortTypeNull:
  213. break;
  214. case kEnginePortTypeAudio: {
  215. CarlaStringList& portList(isInput ? pData->audioInList : pData->audioOutList);
  216. portList.append(name);
  217. return portList.removeOne(name);
  218. }
  219. case kEnginePortTypeCV: {
  220. CarlaStringList& portList(isInput ? pData->cvInList : pData->cvOutList);
  221. return portList.removeOne(name);
  222. }
  223. case kEnginePortTypeEvent: {
  224. CarlaStringList& portList(isInput ? pData->eventInList : pData->eventOutList);
  225. return portList.removeOne(name);
  226. }
  227. }
  228. return false;
  229. }
  230. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  231. CarlaEngineCVSourcePorts* CarlaEngineClient::createCVSourcePorts()
  232. {
  233. pData->cvSourcePorts.setGraphAndPlugin(pData->egraph.getPatchbayGraphOrNull(), pData->plugin);
  234. return &pData->cvSourcePorts;
  235. }
  236. #endif
  237. const CarlaEngine& CarlaEngineClient::getEngine() const noexcept
  238. {
  239. return pData->engine;
  240. }
  241. EngineProcessMode CarlaEngineClient::getProcessMode() const noexcept
  242. {
  243. return pData->engine.getProccessMode();
  244. }
  245. uint CarlaEngineClient::getPortCount(const EnginePortType portType, const bool isInput) const noexcept
  246. {
  247. size_t ret = 0;
  248. switch (portType)
  249. {
  250. case kEnginePortTypeNull:
  251. break;
  252. case kEnginePortTypeAudio:
  253. ret = isInput ? pData->audioInList.count() : pData->audioOutList.count();
  254. break;
  255. case kEnginePortTypeCV:
  256. ret = isInput ? pData->cvInList.count() : pData->cvOutList.count();
  257. break;
  258. case kEnginePortTypeEvent:
  259. ret = isInput ? pData->eventInList.count() : pData->eventOutList.count();
  260. break;
  261. }
  262. return static_cast<uint>(ret);
  263. }
  264. const char* CarlaEngineClient::getAudioPortName(const bool isInput, const uint index) const noexcept
  265. {
  266. CarlaStringList& portList(isInput ? pData->audioInList : pData->audioOutList);
  267. CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr);
  268. return portList.getAt(index);
  269. }
  270. const char* CarlaEngineClient::getCVPortName(const bool isInput, const uint index) const noexcept
  271. {
  272. CarlaStringList& portList(isInput ? pData->cvInList : pData->cvOutList);
  273. CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr);
  274. return portList.getAt(index);
  275. }
  276. const char* CarlaEngineClient::getEventPortName(const bool isInput, const uint index) const noexcept
  277. {
  278. CarlaStringList& portList(isInput ? pData->eventInList : pData->eventOutList);
  279. CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr);
  280. return portList.getAt(index);
  281. }
  282. // -----------------------------------------------------------------------
  283. CARLA_BACKEND_END_NAMESPACE