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.

375 lines
16KB

  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)+10];
  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 CarlaPlugin* const 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);
  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)+10];
  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 CarlaPlugin* const 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);
  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 CarlaPlugin* const 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, index);
  114. char bufName[STR_MAX+1], bufUnit[STR_MAX+1];
  115. carla_zeroChars(bufName, STR_MAX+1);
  116. carla_zeroChars(bufUnit, STR_MAX+1);
  117. if (! plugin->getParameterName(index, bufName))
  118. bufName[0] = '\0';
  119. if (! plugin->getParameterUnit(index, bufUnit))
  120. bufUnit[0] = '\0';
  121. const ParameterData& paramData(plugin->getParameterData(index));
  122. const ParameterRanges& paramRanges(plugin->getParameterRanges(index));
  123. char targetPath[std::strlen(fControlDataTCP.path)+20];
  124. std::strcpy(targetPath, fControlDataTCP.path);
  125. std::strcat(targetPath, "/param");
  126. try_lo_send(fControlDataTCP.target, targetPath, "iiiiiissfffffff",
  127. static_cast<int32_t>(plugin->getId()), static_cast<int32_t>(index),
  128. static_cast<int32_t>(paramData.type), static_cast<int32_t>(paramData.hints),
  129. static_cast<int32_t>(paramData.mappedControlIndex), static_cast<int32_t>(paramData.midiChannel),
  130. bufName, bufUnit,
  131. static_cast<double>(paramRanges.def),
  132. static_cast<double>(paramRanges.min),
  133. static_cast<double>(paramRanges.max),
  134. static_cast<double>(paramRanges.step),
  135. static_cast<double>(paramRanges.stepSmall),
  136. static_cast<double>(paramRanges.stepLarge),
  137. static_cast<double>(plugin->getParameterValue(index)));
  138. }
  139. void CarlaEngineOsc::sendPluginDataCount(const CarlaPlugin* const plugin) const noexcept
  140. {
  141. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  142. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  143. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  144. carla_stdout("CarlaEngineOsc::sendPluginDataCount(%p)", plugin);
  145. char targetPath[std::strlen(fControlDataTCP.path)+7];
  146. std::strcpy(targetPath, fControlDataTCP.path);
  147. std::strcat(targetPath, "/count");
  148. try_lo_send(fControlDataTCP.target, targetPath, "iiiiii",
  149. static_cast<int32_t>(plugin->getId()),
  150. static_cast<int32_t>(plugin->getProgramCount()),
  151. static_cast<int32_t>(plugin->getMidiProgramCount()),
  152. static_cast<int32_t>(plugin->getCustomDataCount()),
  153. static_cast<int32_t>(plugin->getCurrentProgram()),
  154. static_cast<int32_t>(plugin->getCurrentMidiProgram()));
  155. }
  156. void CarlaEngineOsc::sendPluginProgramCount(const CarlaPlugin* const plugin) const noexcept
  157. {
  158. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  159. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  160. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  161. carla_stdout("CarlaEngineOsc::sendPluginDataCount(%p)", plugin);
  162. char targetPath[std::strlen(fControlDataTCP.path)+7];
  163. std::strcpy(targetPath, fControlDataTCP.path);
  164. std::strcat(targetPath, "/pcount");
  165. try_lo_send(fControlDataTCP.target, targetPath, "iii",
  166. static_cast<int32_t>(plugin->getId()),
  167. static_cast<int32_t>(plugin->getProgramCount()),
  168. static_cast<int32_t>(plugin->getMidiProgramCount()));
  169. }
  170. void CarlaEngineOsc::sendPluginProgram(const CarlaPlugin* const plugin, const uint32_t index) const noexcept
  171. {
  172. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  173. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  174. carla_stdout("CarlaEngineOsc::sendPluginProgram(%p, %u)", plugin, index);
  175. char strBuf[STR_MAX+1];
  176. carla_zeroChars(strBuf, STR_MAX+1);
  177. if (! plugin->getProgramName(index, strBuf))
  178. strBuf[0] = '\0';
  179. char targetPath[std::strlen(fControlDataTCP.path)+6];
  180. std::strcpy(targetPath, fControlDataTCP.path);
  181. std::strcat(targetPath, "/prog");
  182. try_lo_send(fControlDataTCP.target, targetPath, "iis",
  183. static_cast<int32_t>(plugin->getId()), static_cast<int32_t>(index), strBuf);
  184. }
  185. void CarlaEngineOsc::sendPluginMidiProgram(const CarlaPlugin* const plugin, const uint32_t index) const noexcept
  186. {
  187. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  188. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  189. carla_stdout("CarlaEngineOsc::sendPluginProgram(%p, %u)", plugin, index);
  190. const MidiProgramData& mpdata(plugin->getMidiProgramData(index));
  191. CARLA_SAFE_ASSERT_RETURN(mpdata.name != nullptr,);
  192. char targetPath[std::strlen(fControlDataTCP.path)+7];
  193. std::strcpy(targetPath, fControlDataTCP.path);
  194. std::strcat(targetPath, "/mprog");
  195. try_lo_send(fControlDataTCP.target, targetPath, "iiiis",
  196. static_cast<int32_t>(plugin->getId()),
  197. static_cast<int32_t>(index),
  198. static_cast<int32_t>(mpdata.bank), static_cast<int32_t>(mpdata.program), mpdata.name);
  199. }
  200. void CarlaEngineOsc::sendPluginCustomData(const CarlaPlugin* const plugin, const uint32_t index) const noexcept
  201. {
  202. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  203. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  204. carla_stdout("CarlaEngineOsc::sendPluginCustomData(%p, %u)", plugin, index);
  205. const CustomData& cdata(plugin->getCustomData(index));
  206. CARLA_SAFE_ASSERT_RETURN(cdata.isValid(),);
  207. char targetPath[std::strlen(fControlDataTCP.path)+7];
  208. std::strcpy(targetPath, fControlDataTCP.path);
  209. std::strcat(targetPath, "/cdata");
  210. try_lo_send(fControlDataTCP.target, targetPath, "iisss",
  211. static_cast<int32_t>(plugin->getId()),
  212. static_cast<int32_t>(index),
  213. cdata.type, cdata.key, cdata.value);
  214. }
  215. void CarlaEngineOsc::sendPluginInternalParameterValues(const CarlaPlugin* const plugin) const noexcept
  216. {
  217. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  218. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  219. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  220. carla_debug("CarlaEngineOsc::sendPluginInternalParameterValues(%p)", plugin);
  221. static_assert(PARAMETER_ACTIVE == -2 && PARAMETER_MAX == -9, "Incorrect data");
  222. double iparams[7];
  223. for (int32_t i = 0; i < 7; ++i)
  224. iparams[i] = plugin->getInternalParameterValue(PARAMETER_ACTIVE - i);
  225. char targetPath[std::strlen(fControlDataTCP.path)+18];
  226. std::strcpy(targetPath, fControlDataTCP.path);
  227. std::strcat(targetPath, "/iparams");
  228. try_lo_send(fControlDataTCP.target, targetPath, "ifffffff",
  229. static_cast<int32_t>(plugin->getId()),
  230. iparams[0], // PARAMETER_ACTIVE
  231. iparams[1], // PARAMETER_DRYWET
  232. iparams[2], // PARAMETER_VOLUME
  233. iparams[3], // PARAMETER_BALANCE_LEFT
  234. iparams[4], // PARAMETER_BALANCE_RIGHT
  235. iparams[5], // PARAMETER_PANNING
  236. iparams[6] // PARAMETER_CTRL_CHANNEL
  237. );
  238. }
  239. // -----------------------------------------------------------------------
  240. void CarlaEngineOsc::sendPing() const noexcept
  241. {
  242. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  243. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  244. char targetPath[std::strlen(fControlDataTCP.path)+6];
  245. std::strcpy(targetPath, fControlDataTCP.path);
  246. std::strcat(targetPath, "/ping");
  247. try_lo_send(fControlDataTCP.target, targetPath, "");
  248. }
  249. void CarlaEngineOsc::sendResponse(const int messageId, const char* const error) const noexcept
  250. {
  251. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  252. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  253. carla_debug("CarlaEngineOsc::sendResponse()");
  254. char targetPath[std::strlen(fControlDataTCP.path)+6];
  255. std::strcpy(targetPath, fControlDataTCP.path);
  256. std::strcat(targetPath, "/resp");
  257. try_lo_send(fControlDataTCP.target, targetPath, "is", messageId, error);
  258. }
  259. void CarlaEngineOsc::sendExit() const noexcept
  260. {
  261. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.path != nullptr && fControlDataTCP.path[0] != '\0',);
  262. CARLA_SAFE_ASSERT_RETURN(fControlDataTCP.target != nullptr,);
  263. carla_debug("CarlaEngineOsc::sendExit()");
  264. char targetPath[std::strlen(fControlDataTCP.path)+6];
  265. std::strcpy(targetPath, fControlDataTCP.path);
  266. std::strcat(targetPath, "/exit");
  267. try_lo_send(fControlDataTCP.target, targetPath, "");
  268. }
  269. // -----------------------------------------------------------------------
  270. void CarlaEngineOsc::sendRuntimeInfo() const noexcept
  271. {
  272. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
  273. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
  274. const EngineTimeInfo timeInfo(fEngine->getTimeInfo());
  275. char targetPath[std::strlen(fControlDataUDP.path)+18];
  276. std::strcpy(targetPath, fControlDataUDP.path);
  277. std::strcat(targetPath, "/runtime");
  278. try_lo_send(fControlDataUDP.target, targetPath, "fiihiiif",
  279. static_cast<double>(fEngine->getDSPLoad()),
  280. static_cast<int32_t>(fEngine->getTotalXruns()),
  281. timeInfo.playing ? 1 : 0,
  282. static_cast<int64_t>(timeInfo.frame),
  283. static_cast<int32_t>(timeInfo.bbt.bar),
  284. static_cast<int32_t>(timeInfo.bbt.beat),
  285. static_cast<int32_t>(timeInfo.bbt.tick),
  286. timeInfo.bbt.beatsPerMinute);
  287. }
  288. void CarlaEngineOsc::sendParameterValue(const uint pluginId, const uint32_t index, const float value) const noexcept
  289. {
  290. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
  291. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
  292. char targetPath[std::strlen(fControlDataUDP.path)+21];
  293. std::strcpy(targetPath, fControlDataUDP.path);
  294. std::strcat(targetPath, "/param");
  295. try_lo_send(fControlDataUDP.target, targetPath, "iif",
  296. static_cast<int32_t>(pluginId),
  297. index,
  298. static_cast<double>(value));
  299. }
  300. void CarlaEngineOsc::sendPeaks(const uint pluginId, const float peaks[4]) const noexcept
  301. {
  302. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.path != nullptr && fControlDataUDP.path[0] != '\0',);
  303. CARLA_SAFE_ASSERT_RETURN(fControlDataUDP.target != nullptr,);
  304. char targetPath[std::strlen(fControlDataUDP.path)+11];
  305. std::strcpy(targetPath, fControlDataUDP.path);
  306. std::strcat(targetPath, "/peaks");
  307. try_lo_send(fControlDataUDP.target, targetPath, "iffff", static_cast<int32_t>(pluginId),
  308. static_cast<double>(peaks[0]),
  309. static_cast<double>(peaks[1]),
  310. static_cast<double>(peaks[2]),
  311. static_cast<double>(peaks[3]));
  312. }
  313. // -----------------------------------------------------------------------
  314. CARLA_BACKEND_END_NAMESPACE
  315. #endif // HAVE_LIBLO