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.

407 lines
17KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2019 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 "CarlaEngineOsc.hpp"
  18. #ifdef HAVE_LIBLO
  19. #include "CarlaBackendUtils.hpp"
  20. #include "CarlaEngine.hpp"
  21. #include "CarlaPlugin.hpp"
  22. CARLA_BACKEND_START_NAMESPACE
  23. static const char* const kNullString = "";
  24. // -----------------------------------------------------------------------
  25. void CarlaEngineOsc::sendCallback(const EngineCallbackOpcode action, const uint pluginId,
  26. const int value1, const int value2, const int value3,
  27. const float valuef, const char* const valueStr) const noexcept
  28. {
  29. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  30. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  31. carla_stdout("CarlaEngineOsc::sendCallback(%i:%s, %i, %i, %i, %i, %f, \"%s\")",
  32. action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3,
  33. static_cast<double>(valuef), valueStr);
  34. char targetPath[std::strlen(fControlDataTCP.path)+4];
  35. std::strcpy(targetPath, fControlDataTCP.path);
  36. std::strcat(targetPath, "/cb");
  37. try_lo_send(fControlDataTCP.target, targetPath, "iiiiifs",
  38. action, pluginId, value1, value2, value3, static_cast<double>(valuef),
  39. valueStr != nullptr ? valueStr : kNullString);
  40. }
  41. void CarlaEngineOsc::sendPluginInfo(const CarlaPluginPtr& plugin) const noexcept
  42. {
  43. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  44. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  45. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  46. carla_stdout("CarlaEngineOsc::sendPluginInfo(%p)", plugin.get());
  47. char bufRealName[STR_MAX+1], bufLabel[STR_MAX+1], bufMaker[STR_MAX+1], bufCopyright[STR_MAX+1];
  48. carla_zeroChars(bufRealName, STR_MAX+1);
  49. carla_zeroChars(bufLabel, STR_MAX+1);
  50. carla_zeroChars(bufMaker, STR_MAX+1);
  51. carla_zeroChars(bufCopyright, STR_MAX+1);
  52. if (! plugin->getRealName(bufRealName))
  53. bufRealName[0] = '\0';
  54. if (! plugin->getLabel(bufLabel))
  55. bufLabel[0] = '\0';
  56. if (! plugin->getMaker(bufMaker))
  57. bufMaker[0] = '\0';
  58. if (! plugin->getCopyright(bufCopyright))
  59. bufCopyright[0] = '\0';
  60. const char* name = plugin->getName();
  61. const char* filename = plugin->getFilename();
  62. const char* iconName = plugin->getIconName();
  63. if (name == nullptr)
  64. name = kNullString;
  65. if (filename == nullptr)
  66. filename = kNullString;
  67. if (iconName == nullptr)
  68. iconName = kNullString;
  69. char targetPath[std::strlen(fControlDataTCP.path)+6];
  70. std::strcpy(targetPath, fControlDataTCP.path);
  71. std::strcat(targetPath, "/info");
  72. try_lo_send(fControlDataTCP.target, targetPath, "iiiihiisssssss",
  73. static_cast<int32_t>(plugin->getId()),
  74. static_cast<int32_t>(plugin->getType()),
  75. static_cast<int32_t>(plugin->getCategory()),
  76. static_cast<int32_t>(plugin->getHints()),
  77. static_cast<int64_t>(plugin->getUniqueId()),
  78. static_cast<int64_t>(plugin->getOptionsAvailable()),
  79. static_cast<int64_t>(plugin->getOptionsEnabled()),
  80. name, filename, iconName,
  81. bufRealName, bufLabel, bufMaker, bufCopyright);
  82. }
  83. void CarlaEngineOsc::sendPluginPortCount(const CarlaPluginPtr& plugin) const noexcept
  84. {
  85. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  86. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  87. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  88. carla_stdout("CarlaEngineOsc::sendPluginPortCount(%p)", plugin.get());
  89. uint32_t paramIns, paramOuts;
  90. plugin->getParameterCountInfo(paramIns, paramOuts);
  91. if (paramIns > 49)
  92. paramIns = 49;
  93. if (paramOuts > 49)
  94. paramOuts = 49;
  95. char targetPath[std::strlen(fControlDataTCP.path)+7];
  96. std::strcpy(targetPath, fControlDataTCP.path);
  97. std::strcat(targetPath, "/ports");
  98. try_lo_send(fControlDataTCP.target, targetPath, "iiiiiiii",
  99. static_cast<int32_t>(plugin->getId()),
  100. static_cast<int32_t>(plugin->getAudioInCount()),
  101. static_cast<int32_t>(plugin->getAudioOutCount()),
  102. static_cast<int32_t>(plugin->getMidiInCount()),
  103. static_cast<int32_t>(plugin->getMidiOutCount()),
  104. static_cast<int32_t>(paramIns),
  105. static_cast<int32_t>(paramOuts),
  106. static_cast<int32_t>(plugin->getParameterCount()));
  107. }
  108. void CarlaEngineOsc::sendPluginParameterInfo(const CarlaPluginPtr& plugin, const uint32_t index) const noexcept
  109. {
  110. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  111. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  112. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  113. carla_debug("CarlaEngineOsc::sendPluginParameterInfo(%p, %u)", plugin.get(), index);
  114. char bufName[STR_MAX+1], bufUnit[STR_MAX+1], bufComment[STR_MAX+1], bufGroupName[STR_MAX+1];
  115. carla_zeroChars(bufName, STR_MAX+1);
  116. carla_zeroChars(bufUnit, STR_MAX+1);
  117. carla_zeroChars(bufComment, STR_MAX+1);
  118. carla_zeroChars(bufGroupName, STR_MAX+1);
  119. if (! plugin->getParameterName(index, bufName))
  120. bufName[0] = '\0';
  121. if (! plugin->getParameterUnit(index, bufUnit))
  122. bufUnit[0] = '\0';
  123. if (! plugin->getParameterComment(index, bufComment))
  124. bufComment[0] = '\0';
  125. if (! plugin->getParameterGroupName(index, bufGroupName))
  126. bufGroupName[0] = '\0';
  127. const ParameterData& paramData(plugin->getParameterData(index));
  128. const ParameterRanges& paramRanges(plugin->getParameterRanges(index));
  129. const int32_t pluginId = static_cast<int32_t>(plugin->getId());
  130. const int32_t paramId = static_cast<int32_t>(index);
  131. char targetPath[std::strlen(fControlDataTCP.path)+13];
  132. std::strcpy(targetPath, fControlDataTCP.path);
  133. std::strcat(targetPath, "/paramInfo");
  134. try_lo_send(fControlDataTCP.target, targetPath, "iissss",
  135. pluginId,
  136. paramId,
  137. bufName,
  138. bufUnit,
  139. bufComment,
  140. bufGroupName);
  141. std::strcpy(targetPath, fControlDataTCP.path);
  142. std::strcat(targetPath, "/paramData");
  143. try_lo_send(fControlDataTCP.target, targetPath, "iiiiiifff",
  144. pluginId,
  145. paramId,
  146. static_cast<int32_t>(paramData.type),
  147. static_cast<int32_t>(paramData.hints),
  148. static_cast<int32_t>(paramData.midiChannel),
  149. static_cast<int32_t>(paramData.mappedControlIndex),
  150. static_cast<double>(paramData.mappedMinimum),
  151. static_cast<double>(paramData.mappedMaximum),
  152. static_cast<double>(plugin->getParameterValue(index)));
  153. std::strcpy(targetPath, fControlDataTCP.path);
  154. std::strcat(targetPath, "/paramRanges");
  155. try_lo_send(fControlDataTCP.target, targetPath, "iiffffff",
  156. pluginId,
  157. paramId,
  158. static_cast<double>(paramRanges.def),
  159. static_cast<double>(paramRanges.min),
  160. static_cast<double>(paramRanges.max),
  161. static_cast<double>(paramRanges.step),
  162. static_cast<double>(paramRanges.stepSmall),
  163. static_cast<double>(paramRanges.stepLarge));
  164. }
  165. void CarlaEngineOsc::sendPluginDataCount(const CarlaPluginPtr& plugin) const noexcept
  166. {
  167. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  168. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  169. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  170. carla_stdout("CarlaEngineOsc::sendPluginDataCount(%p)", plugin.get());
  171. char targetPath[std::strlen(fControlDataTCP.path)+7];
  172. std::strcpy(targetPath, fControlDataTCP.path);
  173. std::strcat(targetPath, "/count");
  174. try_lo_send(fControlDataTCP.target, targetPath, "iiiiii",
  175. static_cast<int32_t>(plugin->getId()),
  176. static_cast<int32_t>(plugin->getProgramCount()),
  177. static_cast<int32_t>(plugin->getMidiProgramCount()),
  178. static_cast<int32_t>(plugin->getCustomDataCount()),
  179. static_cast<int32_t>(plugin->getCurrentProgram()),
  180. static_cast<int32_t>(plugin->getCurrentMidiProgram()));
  181. }
  182. void CarlaEngineOsc::sendPluginProgramCount(const CarlaPluginPtr& plugin) const noexcept
  183. {
  184. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  185. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  186. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  187. carla_stdout("CarlaEngineOsc::sendPluginDataCount(%p)", plugin.get());
  188. char targetPath[std::strlen(fControlDataTCP.path)+7];
  189. std::strcpy(targetPath, fControlDataTCP.path);
  190. std::strcat(targetPath, "/pcount");
  191. try_lo_send(fControlDataTCP.target, targetPath, "iii",
  192. static_cast<int32_t>(plugin->getId()),
  193. static_cast<int32_t>(plugin->getProgramCount()),
  194. static_cast<int32_t>(plugin->getMidiProgramCount()));
  195. }
  196. void CarlaEngineOsc::sendPluginProgram(const CarlaPluginPtr& plugin, const uint32_t index) const noexcept
  197. {
  198. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  199. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  200. carla_stdout("CarlaEngineOsc::sendPluginProgram(%p, %u)", plugin.get(), index);
  201. char strBuf[STR_MAX+1];
  202. carla_zeroChars(strBuf, STR_MAX+1);
  203. if (! plugin->getProgramName(index, strBuf))
  204. strBuf[0] = '\0';
  205. char targetPath[std::strlen(fControlDataTCP.path)+6];
  206. std::strcpy(targetPath, fControlDataTCP.path);
  207. std::strcat(targetPath, "/prog");
  208. try_lo_send(fControlDataTCP.target, targetPath, "iis",
  209. static_cast<int32_t>(plugin->getId()), static_cast<int32_t>(index), strBuf);
  210. }
  211. void CarlaEngineOsc::sendPluginMidiProgram(const CarlaPluginPtr& plugin, const uint32_t index) const noexcept
  212. {
  213. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  214. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  215. carla_stdout("CarlaEngineOsc::sendPluginProgram(%p, %u)", plugin.get(), index);
  216. const MidiProgramData& mpdata(plugin->getMidiProgramData(index));
  217. CARLA_SAFE_ASSERT_RETURN(mpdata.name != nullptr,);
  218. char targetPath[std::strlen(fControlDataTCP.path)+7];
  219. std::strcpy(targetPath, fControlDataTCP.path);
  220. std::strcat(targetPath, "/mprog");
  221. try_lo_send(fControlDataTCP.target, targetPath, "iiiis",
  222. static_cast<int32_t>(plugin->getId()),
  223. static_cast<int32_t>(index),
  224. static_cast<int32_t>(mpdata.bank), static_cast<int32_t>(mpdata.program), mpdata.name);
  225. }
  226. void CarlaEngineOsc::sendPluginCustomData(const CarlaPluginPtr& plugin, const uint32_t index) const noexcept
  227. {
  228. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  229. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  230. carla_stdout("CarlaEngineOsc::sendPluginCustomData(%p, %u)", plugin.get(), index);
  231. const CustomData& cdata(plugin->getCustomData(index));
  232. CARLA_SAFE_ASSERT_RETURN(cdata.isValid(),);
  233. char targetPath[std::strlen(fControlDataTCP.path)+7];
  234. std::strcpy(targetPath, fControlDataTCP.path);
  235. std::strcat(targetPath, "/cdata");
  236. try_lo_send(fControlDataTCP.target, targetPath, "iisss",
  237. static_cast<int32_t>(plugin->getId()),
  238. static_cast<int32_t>(index),
  239. cdata.type, cdata.key, cdata.value);
  240. }
  241. void CarlaEngineOsc::sendPluginInternalParameterValues(const CarlaPluginPtr& plugin) const noexcept
  242. {
  243. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  244. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  245. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  246. carla_debug("CarlaEngineOsc::sendPluginInternalParameterValues(%p)", plugin.get());
  247. #ifdef CARLA_PROPER_CPP11_SUPPORT
  248. static_assert(PARAMETER_ACTIVE == -2 && PARAMETER_MAX == -9, "Incorrect data");
  249. #endif
  250. double iparams[7];
  251. for (int32_t i = 0; i < 7; ++i)
  252. iparams[i] = plugin->getInternalParameterValue(PARAMETER_ACTIVE - i);
  253. char targetPath[std::strlen(fControlDataTCP.path)+9];
  254. std::strcpy(targetPath, fControlDataTCP.path);
  255. std::strcat(targetPath, "/iparams");
  256. try_lo_send(fControlDataTCP.target, targetPath, "ifffffff",
  257. static_cast<int32_t>(plugin->getId()),
  258. iparams[0], // PARAMETER_ACTIVE
  259. iparams[1], // PARAMETER_DRYWET
  260. iparams[2], // PARAMETER_VOLUME
  261. iparams[3], // PARAMETER_BALANCE_LEFT
  262. iparams[4], // PARAMETER_BALANCE_RIGHT
  263. iparams[5], // PARAMETER_PANNING
  264. iparams[6] // PARAMETER_CTRL_CHANNEL
  265. );
  266. }
  267. // -----------------------------------------------------------------------
  268. void CarlaEngineOsc::sendPing() const noexcept
  269. {
  270. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  271. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  272. char targetPath[std::strlen(fControlDataTCP.path)+6];
  273. std::strcpy(targetPath, fControlDataTCP.path);
  274. std::strcat(targetPath, "/ping");
  275. try_lo_send(fControlDataTCP.target, targetPath, "");
  276. }
  277. void CarlaEngineOsc::sendResponse(const int messageId, const char* const error) const noexcept
  278. {
  279. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  280. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  281. carla_debug("CarlaEngineOsc::sendResponse()");
  282. char targetPath[std::strlen(fControlDataTCP.path)+6];
  283. std::strcpy(targetPath, fControlDataTCP.path);
  284. std::strcat(targetPath, "/resp");
  285. try_lo_send(fControlDataTCP.target, targetPath, "is", messageId, error);
  286. }
  287. void CarlaEngineOsc::sendExit() const noexcept
  288. {
  289. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  290. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  291. carla_debug("CarlaEngineOsc::sendExit()");
  292. char targetPath[std::strlen(fControlDataTCP.path)+6];
  293. std::strcpy(targetPath, fControlDataTCP.path);
  294. std::strcat(targetPath, "/exit");
  295. try_lo_send(fControlDataTCP.target, targetPath, "");
  296. }
  297. // -----------------------------------------------------------------------
  298. void CarlaEngineOsc::sendRuntimeInfo() const noexcept
  299. {
  300. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
  301. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
  302. const EngineTimeInfo timeInfo(fEngine->getTimeInfo());
  303. char targetPath[std::strlen(fControlDataUDP.path)+9];
  304. std::strcpy(targetPath, fControlDataUDP.path);
  305. std::strcat(targetPath, "/runtime");
  306. try_lo_send(fControlDataUDP.target, targetPath, "fiihiiif",
  307. static_cast<double>(fEngine->getDSPLoad()),
  308. static_cast<int32_t>(fEngine->getTotalXruns()),
  309. timeInfo.playing ? 1 : 0,
  310. static_cast<int64_t>(timeInfo.frame),
  311. static_cast<int32_t>(timeInfo.bbt.bar),
  312. static_cast<int32_t>(timeInfo.bbt.beat),
  313. static_cast<int32_t>(timeInfo.bbt.tick),
  314. timeInfo.bbt.beatsPerMinute);
  315. }
  316. void CarlaEngineOsc::sendParameterValue(const uint pluginId, const uint32_t index, const float value) const noexcept
  317. {
  318. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
  319. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
  320. char targetPath[std::strlen(fControlDataUDP.path)+7];
  321. std::strcpy(targetPath, fControlDataUDP.path);
  322. std::strcat(targetPath, "/param");
  323. try_lo_send(fControlDataUDP.target, targetPath, "iif",
  324. static_cast<int32_t>(pluginId),
  325. index,
  326. static_cast<double>(value));
  327. }
  328. void CarlaEngineOsc::sendPeaks(const uint pluginId, const float peaks[4]) const noexcept
  329. {
  330. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
  331. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
  332. char targetPath[std::strlen(fControlDataUDP.path)+7];
  333. std::strcpy(targetPath, fControlDataUDP.path);
  334. std::strcat(targetPath, "/peaks");
  335. try_lo_send(fControlDataUDP.target, targetPath, "iffff", static_cast<int32_t>(pluginId),
  336. static_cast<double>(peaks[0]),
  337. static_cast<double>(peaks[1]),
  338. static_cast<double>(peaks[2]),
  339. static_cast<double>(peaks[3]));
  340. }
  341. // -----------------------------------------------------------------------
  342. CARLA_BACKEND_END_NAMESPACE
  343. #endif // HAVE_LIBLO