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.

544 lines
17KB

  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 "CarlaEngine.hpp"
  18. #include "CarlaEngineOsc.hpp"
  19. #include "CarlaPlugin.hpp"
  20. #include "CarlaMIDI.h"
  21. #include <cctype>
  22. CARLA_BACKEND_START_NAMESPACE
  23. // -----------------------------------------------------------------------
  24. CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine) noexcept
  25. : fEngine(engine),
  26. #ifndef BUILD_BRIDGE
  27. fControlData(),
  28. #endif
  29. fName(),
  30. fServerPathTCP(),
  31. fServerPathUDP(),
  32. fServerTCP(nullptr),
  33. fServerUDP(nullptr),
  34. leakDetector_CarlaEngineOsc()
  35. {
  36. CARLA_SAFE_ASSERT(engine != nullptr);
  37. carla_debug("CarlaEngineOsc::CarlaEngineOsc(%p)", engine);
  38. }
  39. CarlaEngineOsc::~CarlaEngineOsc() noexcept
  40. {
  41. CARLA_SAFE_ASSERT(fName.isEmpty());
  42. CARLA_SAFE_ASSERT(fServerPathTCP.isEmpty());
  43. CARLA_SAFE_ASSERT(fServerPathUDP.isEmpty());
  44. CARLA_SAFE_ASSERT(fServerTCP == nullptr);
  45. CARLA_SAFE_ASSERT(fServerUDP == nullptr);
  46. carla_debug("CarlaEngineOsc::~CarlaEngineOsc()");
  47. }
  48. // -----------------------------------------------------------------------
  49. void CarlaEngineOsc::init(const char* const name) noexcept
  50. {
  51. CARLA_SAFE_ASSERT_RETURN(fName.isEmpty(),);
  52. CARLA_SAFE_ASSERT_RETURN(fServerPathTCP.isEmpty(),);
  53. CARLA_SAFE_ASSERT_RETURN(fServerPathUDP.isEmpty(),);
  54. CARLA_SAFE_ASSERT_RETURN(fServerTCP == nullptr,);
  55. CARLA_SAFE_ASSERT_RETURN(fServerUDP == nullptr,);
  56. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
  57. carla_debug("CarlaEngineOsc::init(\"%s\")", name);
  58. fName = name;
  59. fName.toBasic();
  60. fServerTCP = lo_server_new_with_proto(nullptr, LO_TCP, osc_error_handler_TCP);
  61. if (fServerTCP != nullptr)
  62. {
  63. if (char* const tmpServerPathTCP = lo_server_get_url(fServerTCP))
  64. {
  65. fServerPathTCP = tmpServerPathTCP;
  66. fServerPathTCP += fName;
  67. std::free(tmpServerPathTCP);
  68. }
  69. lo_server_add_method(fServerTCP, nullptr, nullptr, osc_message_handler_TCP, this);
  70. }
  71. fServerUDP = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler_UDP);
  72. if (fServerUDP != nullptr)
  73. {
  74. if (char* const tmpServerPathUDP = lo_server_get_url(fServerUDP))
  75. {
  76. fServerPathUDP = tmpServerPathUDP;
  77. fServerPathUDP += fName;
  78. std::free(tmpServerPathUDP);
  79. }
  80. lo_server_add_method(fServerUDP, nullptr, nullptr, osc_message_handler_UDP, this);
  81. }
  82. CARLA_SAFE_ASSERT(fName.isNotEmpty());
  83. CARLA_SAFE_ASSERT(fServerPathTCP.isNotEmpty());
  84. CARLA_SAFE_ASSERT(fServerPathUDP.isNotEmpty());
  85. CARLA_SAFE_ASSERT(fServerTCP != nullptr);
  86. CARLA_SAFE_ASSERT(fServerUDP != nullptr);
  87. }
  88. void CarlaEngineOsc::idle() const noexcept
  89. {
  90. if (fServerTCP != nullptr)
  91. {
  92. for (;;)
  93. {
  94. try {
  95. if (lo_server_recv_noblock(fServerTCP, 0) == 0)
  96. break;
  97. } CARLA_SAFE_EXCEPTION_CONTINUE("OSC idle TCP")
  98. }
  99. }
  100. if (fServerUDP != nullptr)
  101. {
  102. for (;;)
  103. {
  104. try {
  105. if (lo_server_recv_noblock(fServerUDP, 0) == 0)
  106. break;
  107. } CARLA_SAFE_EXCEPTION_CONTINUE("OSC idle UDP")
  108. }
  109. }
  110. }
  111. void CarlaEngineOsc::close() noexcept
  112. {
  113. CARLA_SAFE_ASSERT(fName.isNotEmpty());
  114. CARLA_SAFE_ASSERT(fServerPathTCP.isNotEmpty());
  115. CARLA_SAFE_ASSERT(fServerPathUDP.isNotEmpty());
  116. CARLA_SAFE_ASSERT(fServerTCP != nullptr);
  117. CARLA_SAFE_ASSERT(fServerUDP != nullptr);
  118. carla_debug("CarlaEngineOsc::close()");
  119. fName.clear();
  120. if (fServerTCP != nullptr)
  121. {
  122. lo_server_del_method(fServerTCP, nullptr, nullptr);
  123. lo_server_free(fServerTCP);
  124. fServerTCP = nullptr;
  125. }
  126. if (fServerUDP != nullptr)
  127. {
  128. lo_server_del_method(fServerUDP, nullptr, nullptr);
  129. lo_server_free(fServerUDP);
  130. fServerUDP = nullptr;
  131. }
  132. fServerPathTCP.clear();
  133. fServerPathUDP.clear();
  134. #ifndef BUILD_BRIDGE
  135. fControlData.clear();
  136. #endif
  137. }
  138. // -----------------------------------------------------------------------
  139. int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg)
  140. {
  141. CARLA_SAFE_ASSERT_RETURN(fName.isNotEmpty(), 1);
  142. CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', 1);
  143. #ifdef DEBUG
  144. if (std::strstr(path, "/bridge_pong") == nullptr) {
  145. carla_debug("CarlaEngineOsc::handleMessage(%s, \"%s\", %i, %p, \"%s\", %p)", bool2str(isTCP), path, argc, argv, types, msg);
  146. }
  147. #endif
  148. //if (isTCP)
  149. {
  150. CARLA_SAFE_ASSERT_RETURN(fServerPathTCP.isNotEmpty(), 1);
  151. CARLA_SAFE_ASSERT_RETURN(fServerTCP != nullptr, 1);
  152. }
  153. //else
  154. {
  155. CARLA_SAFE_ASSERT_RETURN(fServerPathUDP.isNotEmpty(), 1);
  156. CARLA_SAFE_ASSERT_RETURN(fServerUDP != nullptr, 1);
  157. }
  158. #ifndef BUILD_BRIDGE
  159. // Initial path check
  160. if (std::strcmp(path, "/register") == 0)
  161. {
  162. const lo_address source(lo_message_get_source(msg));
  163. return handleMsgRegister(isTCP, argc, argv, types, source);
  164. }
  165. if (std::strcmp(path, "/unregister") == 0)
  166. {
  167. return handleMsgUnregister();
  168. }
  169. #endif
  170. const std::size_t nameSize(fName.length());
  171. // Check if message is for this client
  172. if (std::strlen(path) <= nameSize || std::strncmp(path+1, fName, nameSize) != 0)
  173. {
  174. carla_stderr("CarlaEngineOsc::handleMessage() - message not for this client -> '%s' != '/%s/'", path, fName.buffer());
  175. return 1;
  176. }
  177. // Get plugin id from path, "/carla/23/method" -> 23
  178. uint pluginId = 0;
  179. std::size_t offset;
  180. if (std::isdigit(path[nameSize+2]))
  181. {
  182. if (std::isdigit(path[nameSize+3]))
  183. {
  184. if (std::isdigit(path[nameSize+5]))
  185. {
  186. carla_stderr2("CarlaEngineOsc::handleMessage() - invalid plugin id, over 999? (value: \"%s\")", path+(nameSize+1));
  187. return 1;
  188. }
  189. else if (std::isdigit(path[nameSize+4]))
  190. {
  191. // 3 digits, /xyz/method
  192. offset = 6;
  193. pluginId += uint(path[nameSize+2]-'0')*100;
  194. pluginId += uint(path[nameSize+3]-'0')*10;
  195. pluginId += uint(path[nameSize+4]-'0');
  196. }
  197. else
  198. {
  199. // 2 digits, /xy/method
  200. offset = 5;
  201. pluginId += uint(path[nameSize+2]-'0')*10;
  202. pluginId += uint(path[nameSize+3]-'0');
  203. }
  204. }
  205. else
  206. {
  207. // single digit, /x/method
  208. offset = 4;
  209. pluginId += uint(path[nameSize+2]-'0');
  210. }
  211. }
  212. else
  213. {
  214. carla_stderr("CarlaEngineOsc::handleMessage() - invalid message '%s'", path);
  215. return 1;
  216. }
  217. if (pluginId > fEngine->getCurrentPluginCount())
  218. {
  219. carla_stderr("CarlaEngineOsc::handleMessage() - failed to get plugin, wrong id '%i'", pluginId);
  220. return 0;
  221. }
  222. // Get plugin
  223. CarlaPlugin* const plugin(fEngine->getPluginUnchecked(pluginId));
  224. if (plugin == nullptr || plugin->getId() != pluginId)
  225. {
  226. carla_stderr("CarlaEngineOsc::handleMessage() - invalid plugin id '%i', probably has been removed (path: '%s')", pluginId, path);
  227. return 0;
  228. }
  229. // Get method from path, "/Carla/i/method" -> "method"
  230. char method[32+1];
  231. method[32] = '\0';
  232. std::strncpy(method, path + (nameSize + offset), 32);
  233. if (method[0] == '\0')
  234. {
  235. carla_stderr("CarlaEngineOsc::handleMessage(%s, \"%s\", ...) - received message without method", bool2str(isTCP), path);
  236. return 0;
  237. }
  238. #ifndef BUILD_BRIDGE
  239. // Internal methods
  240. if (std::strcmp(method, "set_active") == 0)
  241. return handleMsgSetActive(plugin, argc, argv, types);
  242. if (std::strcmp(method, "set_drywet") == 0)
  243. return handleMsgSetDryWet(plugin, argc, argv, types);
  244. if (std::strcmp(method, "set_volume") == 0)
  245. return handleMsgSetVolume(plugin, argc, argv, types);
  246. if (std::strcmp(method, "set_balance_left") == 0)
  247. return handleMsgSetBalanceLeft(plugin, argc, argv, types);
  248. if (std::strcmp(method, "set_balance_right") == 0)
  249. return handleMsgSetBalanceRight(plugin, argc, argv, types);
  250. if (std::strcmp(method, "set_panning") == 0)
  251. return handleMsgSetPanning(plugin, argc, argv, types);
  252. if (std::strcmp(method, "set_parameter_value") == 0)
  253. return handleMsgSetParameterValue(plugin, argc, argv, types);
  254. if (std::strcmp(method, "set_parameter_midi_cc") == 0)
  255. return handleMsgSetParameterMidiCC(plugin, argc, argv, types);
  256. if (std::strcmp(method, "set_parameter_midi_channel") == 0)
  257. return handleMsgSetParameterMidiChannel(plugin, argc, argv, types);
  258. if (std::strcmp(method, "set_program") == 0)
  259. return handleMsgSetProgram(plugin, argc, argv, types);
  260. if (std::strcmp(method, "set_midi_program") == 0)
  261. return handleMsgSetMidiProgram(plugin, argc, argv, types);
  262. if (std::strcmp(method, "note_on") == 0)
  263. return handleMsgNoteOn(plugin, argc, argv, types);
  264. if (std::strcmp(method, "note_off") == 0)
  265. return handleMsgNoteOff(plugin, argc, argv, types);
  266. #endif
  267. // Send all other methods to plugins, TODO
  268. plugin->handleOscMessage(method, argc, argv, types, msg);
  269. return 0;
  270. }
  271. // -----------------------------------------------------------------------
  272. #ifndef BUILD_BRIDGE
  273. int CarlaEngineOsc::handleMsgRegister(const bool isTCP, const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source)
  274. {
  275. carla_debug("CarlaEngineOsc::handleMsgRegister()");
  276. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s");
  277. if (fControlData.path != nullptr)
  278. {
  279. carla_stderr("CarlaEngineOsc::handleMsgRegister() - OSC backend already registered to %s", fControlData.path);
  280. return 1;
  281. }
  282. const char* const url = &argv[0]->s;
  283. carla_debug("CarlaEngineOsc::handleMsgRegister() - OSC backend registered to %s", url);
  284. {
  285. const char* host = lo_address_get_hostname(source);
  286. const char* port = lo_address_get_port(source);
  287. fControlData.source = lo_address_new_with_proto(isTCP ? LO_TCP : LO_UDP, host, port);
  288. }
  289. {
  290. char* host = lo_url_get_hostname(url);
  291. char* port = lo_url_get_port(url);
  292. fControlData.path = carla_strdup_free(lo_url_get_path(url));
  293. fControlData.target = lo_address_new_with_proto(isTCP ? LO_TCP : LO_UDP, host, port);
  294. std::free(host);
  295. std::free(port);
  296. }
  297. for (uint i=0, count=fEngine->getCurrentPluginCount(); i < count; ++i)
  298. {
  299. CarlaPlugin* const plugin(fEngine->getPluginUnchecked(i));
  300. if (plugin != nullptr && plugin->isEnabled())
  301. plugin->registerToOscClient();
  302. }
  303. return 0;
  304. }
  305. int CarlaEngineOsc::handleMsgUnregister()
  306. {
  307. carla_debug("CarlaEngineOsc::handleMsgUnregister()");
  308. if (fControlData.path == nullptr)
  309. {
  310. carla_stderr("CarlaEngineOsc::handleMsgUnregister() - OSC backend is not registered yet");
  311. return 1;
  312. }
  313. fControlData.clear();
  314. return 0;
  315. }
  316. // -----------------------------------------------------------------------
  317. int CarlaEngineOsc::handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS)
  318. {
  319. carla_debug("CarlaEngineOsc::handleMsgSetActive()");
  320. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  321. const bool active = (argv[0]->i != 0);
  322. plugin->setActive(active, false, true);
  323. return 0;
  324. }
  325. int CarlaEngineOsc::handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS)
  326. {
  327. carla_debug("CarlaEngineOsc::handleMsgSetDryWet()");
  328. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  329. const float value = argv[0]->f;
  330. plugin->setDryWet(value, false, true);
  331. return 0;
  332. }
  333. int CarlaEngineOsc::handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS)
  334. {
  335. carla_debug("CarlaEngineOsc::handleMsgSetVolume()");
  336. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  337. const float value = argv[0]->f;
  338. plugin->setVolume(value, false, true);
  339. return 0;
  340. }
  341. int CarlaEngineOsc::handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS)
  342. {
  343. carla_debug("CarlaEngineOsc::handleMsgSetBalanceLeft()");
  344. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  345. const float value = argv[0]->f;
  346. plugin->setBalanceLeft(value, false, true);
  347. return 0;
  348. }
  349. int CarlaEngineOsc::handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS)
  350. {
  351. carla_debug("CarlaEngineOsc::handleMsgSetBalanceRight()");
  352. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  353. const float value = argv[0]->f;
  354. plugin->setBalanceRight(value, false, true);
  355. return 0;
  356. }
  357. int CarlaEngineOsc::handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS)
  358. {
  359. carla_debug("CarlaEngineOsc::handleMsgSetPanning()");
  360. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  361. const float value = argv[0]->f;
  362. plugin->setPanning(value, false, true);
  363. return 0;
  364. }
  365. int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS)
  366. {
  367. carla_debug("CarlaEngineOsc::handleMsgSetParameterValue()");
  368. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if");
  369. const int32_t index = argv[0]->i;
  370. const float value = argv[1]->f;
  371. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  372. plugin->setParameterValue(static_cast<uint32_t>(index), value, true, false, true);
  373. return 0;
  374. }
  375. int CarlaEngineOsc::handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS)
  376. {
  377. carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiCC()");
  378. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  379. const int32_t index = argv[0]->i;
  380. const int32_t cc = argv[1]->i;
  381. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  382. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL, 0);
  383. plugin->setParameterMidiCC(static_cast<uint32_t>(index), static_cast<int16_t>(cc), false, true);
  384. return 0;
  385. }
  386. int CarlaEngineOsc::handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS)
  387. {
  388. carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiChannel()");
  389. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  390. const int32_t index = argv[0]->i;
  391. const int32_t channel = argv[1]->i;
  392. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  393. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  394. plugin->setParameterMidiChannel(static_cast<uint32_t>(index), static_cast<uint8_t>(channel), false, true);
  395. return 0;
  396. }
  397. int CarlaEngineOsc::handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS)
  398. {
  399. carla_debug("CarlaEngineOsc::handleMsgSetProgram()");
  400. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  401. const int32_t index = argv[0]->i;
  402. CARLA_SAFE_ASSERT_RETURN(index >= -1, 0);
  403. plugin->setProgram(index, true, false, true);
  404. return 0;
  405. }
  406. int CarlaEngineOsc::handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS)
  407. {
  408. carla_debug("CarlaEngineOsc::handleMsgSetMidiProgram()");
  409. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  410. const int32_t index = argv[0]->i;
  411. CARLA_SAFE_ASSERT_RETURN(index >= -1, 0);
  412. plugin->setMidiProgram(index, true, false, true);
  413. return 0;
  414. }
  415. int CarlaEngineOsc::handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS)
  416. {
  417. carla_debug("CarlaEngineOsc::handleMsgNoteOn()");
  418. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(3, "iii");
  419. const int32_t channel = argv[0]->i;
  420. const int32_t note = argv[1]->i;
  421. const int32_t velo = argv[2]->i;
  422. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  423. CARLA_SAFE_ASSERT_RETURN(note >= 0 && note < MAX_MIDI_NOTE, 0);
  424. CARLA_SAFE_ASSERT_RETURN(velo >= 0 && velo < MAX_MIDI_VALUE, 0);
  425. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), static_cast<uint8_t>(velo), true, false, true);
  426. return 0;
  427. }
  428. int CarlaEngineOsc::handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS)
  429. {
  430. carla_debug("CarlaEngineOsc::handleMsgNoteOff()");
  431. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  432. const int32_t channel = argv[0]->i;
  433. const int32_t note = argv[1]->i;
  434. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  435. CARLA_SAFE_ASSERT_RETURN(note >= 0 && note < MAX_MIDI_NOTE, 0);
  436. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), 0, true, false, true);
  437. return 0;
  438. }
  439. #endif // ! BUILD_BRIDGE
  440. // -----------------------------------------------------------------------
  441. CARLA_BACKEND_END_NAMESPACE