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.

788 lines
26KB

  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 "CarlaEngineInternal.hpp"
  20. #include "CarlaPlugin.hpp"
  21. #include "CarlaMIDI.h"
  22. #include <cctype>
  23. CARLA_BACKEND_START_NAMESPACE
  24. // -----------------------------------------------------------------------
  25. int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path,
  26. const int argc, const lo_arg* const* const argv, const char* const types,
  27. const lo_message msg)
  28. {
  29. CARLA_SAFE_ASSERT_RETURN(fName.isNotEmpty(), 1);
  30. CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', 1);
  31. CARLA_SAFE_ASSERT_RETURN(path[0] == '/', 1);
  32. #ifdef DEBUG
  33. if (std::strncmp(path, "/bridge_pong", 12) != 0) {
  34. carla_debug("CarlaEngineOsc::handleMessage(%s, \"%s\", %i, %p, \"%s\", %p)",
  35. bool2str(isTCP), path, argc, argv, types, msg);
  36. }
  37. #endif
  38. if (isTCP)
  39. {
  40. CARLA_SAFE_ASSERT_RETURN(fServerPathTCP.isNotEmpty(), 1);
  41. CARLA_SAFE_ASSERT_RETURN(fServerTCP != nullptr, 1);
  42. }
  43. else
  44. {
  45. CARLA_SAFE_ASSERT_RETURN(fServerPathUDP.isNotEmpty(), 1);
  46. CARLA_SAFE_ASSERT_RETURN(fServerUDP != nullptr, 1);
  47. }
  48. const lo_address source = lo_message_get_source(msg);
  49. // Initial path check
  50. if (std::strcmp(path, "/register") == 0)
  51. return handleMsgRegister(isTCP, argc, argv, types, source);
  52. if (std::strcmp(path, "/unregister") == 0)
  53. return handleMsgUnregister(isTCP, argc, argv, types);
  54. if (std::strncmp(path, "/ctrl/", 6) == 0)
  55. {
  56. CARLA_SAFE_ASSERT_RETURN(isTCP, 1);
  57. return handleMsgControl(path + 6, argc, argv, types);
  58. }
  59. // Check if message is for this client
  60. std::size_t bytesAfterName;
  61. if (fControlDataTCP.owner != nullptr && std::strcmp(lo_address_get_hostname(source), fControlDataTCP.owner) == 0)
  62. {
  63. if (const char* const slash = std::strchr(path, '/'))
  64. {
  65. bytesAfterName = static_cast<std::size_t>(slash - path) + 1U;
  66. }
  67. else
  68. {
  69. carla_stderr("CarlaEngineOsc::handleMessage() - message '%s' is invalid", path);
  70. return 1;
  71. }
  72. }
  73. else
  74. {
  75. bytesAfterName = fName.length();
  76. if (std::strlen(path) <= bytesAfterName || std::strncmp(path+1, fName, bytesAfterName) != 0)
  77. {
  78. carla_stderr("CarlaEngineOsc::handleMessage() - message not for this client -> '%s' != '/%s/'",
  79. path, fName.buffer());
  80. return 1;
  81. }
  82. }
  83. // Get plugin id from path, "/carla/23/method" -> 23
  84. uint pluginId = 0;
  85. std::size_t offset;
  86. if (! std::isdigit(path[bytesAfterName+2]))
  87. {
  88. carla_stderr("CarlaEngineOsc::handleMessage() - invalid message '%s'", path);
  89. return 1;
  90. }
  91. if (std::isdigit(path[bytesAfterName+3]))
  92. {
  93. if (std::isdigit(path[bytesAfterName+5]))
  94. {
  95. carla_stderr2("CarlaEngineOsc::handleMessage() - invalid plugin id, over 999? (value: \"%s\")",
  96. path+(bytesAfterName+1));
  97. return 1;
  98. }
  99. else if (std::isdigit(path[bytesAfterName+4]))
  100. {
  101. // 3 digits, /xyz/method
  102. offset = 6;
  103. pluginId += uint(path[bytesAfterName+2]-'0')*100;
  104. pluginId += uint(path[bytesAfterName+3]-'0')*10;
  105. pluginId += uint(path[bytesAfterName+4]-'0');
  106. }
  107. else
  108. {
  109. // 2 digits, /xy/method
  110. offset = 5;
  111. pluginId += uint(path[bytesAfterName+2]-'0')*10;
  112. pluginId += uint(path[bytesAfterName+3]-'0');
  113. }
  114. }
  115. else
  116. {
  117. // single digit, /x/method
  118. offset = 4;
  119. pluginId += uint(path[bytesAfterName+2]-'0');
  120. }
  121. if (pluginId > fEngine->getCurrentPluginCount())
  122. {
  123. carla_stderr("CarlaEngineOsc::handleMessage() - failed to get plugin, wrong id '%i'", pluginId);
  124. return 0;
  125. }
  126. // Get plugin
  127. const CarlaPluginPtr plugin = fEngine->getPluginUnchecked(pluginId);
  128. if (plugin == nullptr || plugin->getId() != pluginId)
  129. {
  130. carla_stderr("CarlaEngineOsc::handleMessage() - invalid plugin id '%i', probably has been removed (path: '%s')", pluginId, path);
  131. return 0;
  132. }
  133. // Get method from path, "/Carla/i/method" -> "method"
  134. char method[48];
  135. std::strncpy(method, path + (bytesAfterName + offset), 47);
  136. method[47] = '\0';
  137. if (method[0] == '\0')
  138. {
  139. carla_stderr("CarlaEngineOsc::handleMessage(%s, \"%s\", ...) - received message without method", bool2str(isTCP), path);
  140. return 0;
  141. }
  142. // Internal methods
  143. if (std::strcmp(method, "set_option") == 0)
  144. return 0; //handleMsgSetOption(plugin, argc, argv, types); // TODO
  145. if (std::strcmp(method, "set_active") == 0)
  146. return handleMsgSetActive(plugin, argc, argv, types);
  147. if (std::strcmp(method, "set_drywet") == 0)
  148. return handleMsgSetDryWet(plugin, argc, argv, types);
  149. if (std::strcmp(method, "set_volume") == 0)
  150. return handleMsgSetVolume(plugin, argc, argv, types);
  151. if (std::strcmp(method, "set_balance_left") == 0)
  152. return handleMsgSetBalanceLeft(plugin, argc, argv, types);
  153. if (std::strcmp(method, "set_balance_right") == 0)
  154. return handleMsgSetBalanceRight(plugin, argc, argv, types);
  155. if (std::strcmp(method, "set_panning") == 0)
  156. return handleMsgSetPanning(plugin, argc, argv, types);
  157. if (std::strcmp(method, "set_ctrl_channel") == 0)
  158. return 0; //handleMsgSetControlChannel(plugin, argc, argv, types); // TODO
  159. if (std::strcmp(method, "set_parameter_value") == 0)
  160. return handleMsgSetParameterValue(plugin, argc, argv, types);
  161. if (std::strcmp(method, "set_parameter_mapped_control_index") == 0)
  162. return handleMsgSetParameterMappedControlIndex(plugin, argc, argv, types);
  163. if (std::strcmp(method, "set_parameter_mapped_range") == 0)
  164. return handleMsgSetParameterMappedRange(plugin, argc, argv, types);
  165. if (std::strcmp(method, "set_parameter_midi_channel") == 0)
  166. return handleMsgSetParameterMidiChannel(plugin, argc, argv, types);
  167. if (std::strcmp(method, "set_program") == 0)
  168. return handleMsgSetProgram(plugin, argc, argv, types);
  169. if (std::strcmp(method, "set_midi_program") == 0)
  170. return handleMsgSetMidiProgram(plugin, argc, argv, types);
  171. if (std::strcmp(method, "set_custom_data") == 0)
  172. return 0; //handleMsgSetCustomData(plugin, argc, argv, types); // TODO
  173. if (std::strcmp(method, "set_chunk") == 0)
  174. return 0; //handleMsgSetChunk(plugin, argc, argv, types); // TODO
  175. if (std::strcmp(method, "note_on") == 0)
  176. return handleMsgNoteOn(plugin, argc, argv, types);
  177. if (std::strcmp(method, "note_off") == 0)
  178. return handleMsgNoteOff(plugin, argc, argv, types);
  179. // Send all other methods to plugins, TODO
  180. plugin->handleOscMessage(method, argc, argv, types, msg);
  181. return 0;
  182. }
  183. // -----------------------------------------------------------------------
  184. int CarlaEngineOsc::handleMsgRegister(const bool isTCP,
  185. const int argc, const lo_arg* const* const argv, const char* const types,
  186. const lo_address source)
  187. {
  188. carla_debug("CarlaEngineOsc::handleMsgRegister()");
  189. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s");
  190. const char* const url = &argv[0]->s;
  191. CarlaOscData& oscData(isTCP ? fControlDataTCP : fControlDataUDP);
  192. if (oscData.owner != nullptr)
  193. {
  194. carla_stderr("OSC backend already registered to %s", oscData.owner);
  195. char* const path = lo_url_get_path(url);
  196. const size_t pathlen = std::strlen(path);
  197. CARLA_SAFE_ASSERT_RETURN(pathlen < 32, 0);
  198. char targetPath[pathlen+12];
  199. std::strcpy(targetPath, path);
  200. std::strcat(targetPath, "/exit-error");
  201. lo_send_from(source, isTCP ? fServerTCP : fServerUDP, LO_TT_IMMEDIATE,
  202. targetPath, "s", "OSC already registered to another client");
  203. free(path);
  204. }
  205. else
  206. {
  207. const char* const host = lo_address_get_hostname(source);
  208. /* */ char* const port = lo_url_get_port(url); // NOTE: lo_address_get_port is buggy against TCP
  209. const lo_address target = lo_address_new_with_proto(isTCP ? LO_TCP : LO_UDP, host, port);
  210. oscData.owner = carla_strdup_safe(host);
  211. oscData.path = carla_strdup_free(lo_url_get_path(url));
  212. oscData.target = target;
  213. char* const targeturl = lo_address_get_url(target);
  214. carla_stdout("OSC %s backend registered to %s, path: %s, target: %s (host: %s, port: %s)",
  215. isTCP ? "TCP" : "UDP", url, oscData.path, targeturl, host, port);
  216. free(targeturl);
  217. free(port);
  218. if (isTCP)
  219. {
  220. const EngineOptions& opts(fEngine->getOptions());
  221. fEngine->callback(false, true,
  222. ENGINE_CALLBACK_ENGINE_STARTED,
  223. fEngine->getCurrentPluginCount(),
  224. opts.processMode,
  225. opts.transportMode,
  226. static_cast<int>(fEngine->getBufferSize()),
  227. static_cast<float>(fEngine->getSampleRate()),
  228. fEngine->getCurrentDriverName());
  229. for (uint i=0, count=fEngine->getCurrentPluginCount(); i < count; ++i)
  230. {
  231. const CarlaPluginPtr plugin = fEngine->getPluginUnchecked(i);
  232. CARLA_SAFE_ASSERT_CONTINUE(plugin != nullptr);
  233. fEngine->callback(false, true, ENGINE_CALLBACK_PLUGIN_ADDED, i, 0, 0, 0, 0.0f, plugin->getName());
  234. }
  235. fEngine->patchbayRefresh(false, true, fEngine->pData->graph.isUsingExternalOSC());
  236. }
  237. }
  238. return 0;
  239. }
  240. int CarlaEngineOsc::handleMsgUnregister(const bool isTCP,
  241. const int argc, const lo_arg* const* const argv, const char* const types)
  242. {
  243. carla_debug("CarlaEngineOsc::handleMsgUnregister()");
  244. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s");
  245. CarlaOscData& oscData(isTCP ? fControlDataTCP : fControlDataUDP);
  246. if (oscData.owner == nullptr)
  247. {
  248. carla_stderr("OSC backend is not registered yet, unregister failed");
  249. return 0;
  250. }
  251. const char* const url = &argv[0]->s;
  252. if (std::strcmp(oscData.owner, url) == 0)
  253. {
  254. carla_stdout("OSC client %s unregistered", url);
  255. oscData.clear();
  256. return 0;
  257. }
  258. carla_stderr("OSC backend unregister failed, current owner %s does not match requested %s", oscData.owner, url);
  259. return 0;
  260. }
  261. int CarlaEngineOsc::handleMsgControl(const char* const method,
  262. const int argc, const lo_arg* const* const argv, const char* const types)
  263. {
  264. carla_debug("CarlaEngineOsc::handleMsgControl()");
  265. CARLA_SAFE_ASSERT_RETURN(method != nullptr && method[0] != '\0', 0);
  266. CARLA_SAFE_ASSERT_RETURN(types != nullptr, 0);
  267. CARLA_SAFE_ASSERT_RETURN(types[0] == 'i', 0);
  268. if (fControlDataTCP.owner == nullptr)
  269. {
  270. carla_stderr("OSC backend is not registered yet, control failed");
  271. return 0;
  272. }
  273. const int32_t messageId = argv[0]->i;
  274. bool ok;
  275. #define CARLA_SAFE_ASSERT_RETURN_OSC_ERR(cond) \
  276. if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); sendResponse(messageId, #cond); return 0; }
  277. /**/ if (std::strcmp(method, "clear_engine_xruns") == 0)
  278. {
  279. ok = true;
  280. fEngine->clearXruns();
  281. }
  282. else if (std::strcmp(method, "cancel_engine_action") == 0)
  283. {
  284. ok = true;
  285. fEngine->setActionCanceled(true);
  286. }
  287. else if (std::strcmp(method, "patchbay_connect") == 0)
  288. {
  289. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 6);
  290. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  291. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i');
  292. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[3] == 'i');
  293. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[4] == 'i');
  294. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[5] == 'i');
  295. const bool external = argv[1]->i != 0;
  296. const int32_t groupA = argv[2]->i;
  297. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(groupA >= 0);
  298. const int32_t portA = argv[3]->i;
  299. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(portA >= 0);
  300. const int32_t groupB = argv[4]->i;
  301. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(groupB >= 0);
  302. const int32_t portB = argv[5]->i;
  303. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(portB >= 0);
  304. ok = fEngine->patchbayConnect(external,
  305. static_cast<uint32_t>(groupA),
  306. static_cast<uint32_t>(portA),
  307. static_cast<uint32_t>(groupB),
  308. static_cast<uint32_t>(portB));
  309. }
  310. else if (std::strcmp(method, "patchbay_disconnect") == 0)
  311. {
  312. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 3);
  313. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  314. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i');
  315. const bool external = argv[1]->i != 0;
  316. const int32_t connectionId = argv[2]->i;
  317. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(connectionId >= 0);
  318. ok = fEngine->patchbayDisconnect(external, static_cast<uint32_t>(connectionId));
  319. }
  320. else if (std::strcmp(method, "patchbay_set_group_pos") == 0)
  321. {
  322. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 7);
  323. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  324. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i');
  325. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[3] == 'i');
  326. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[4] == 'i');
  327. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[5] == 'i');
  328. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[6] == 'i');
  329. const bool external = argv[1]->i != 0;
  330. const int32_t groupId = argv[2]->i;
  331. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(groupId >= 0);
  332. ok = fEngine->patchbaySetGroupPos(true, false,
  333. external, static_cast<uint32_t>(groupId),
  334. argv[3]->i, argv[4]->i, argv[5]->i, argv[6]->i);
  335. }
  336. else if (std::strcmp(method, "patchbay_refresh") == 0)
  337. {
  338. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2);
  339. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  340. const bool external = argv[1]->i != 0;
  341. ok = fEngine->patchbayRefresh(false, true, external);
  342. }
  343. else if (std::strcmp(method, "transport_play") == 0)
  344. {
  345. ok = true;
  346. fEngine->transportPlay();
  347. }
  348. else if (std::strcmp(method, "transport_pause") == 0)
  349. {
  350. ok = true;
  351. fEngine->transportPause();
  352. }
  353. else if (std::strcmp(method, "transport_bpm") == 0)
  354. {
  355. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2);
  356. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'f');
  357. const double bpm = argv[1]->f;
  358. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(bpm >= 0.0);
  359. ok = true;
  360. fEngine->transportBPM(bpm);
  361. }
  362. else if (std::strcmp(method, "transport_relocate") == 0)
  363. {
  364. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2);
  365. uint64_t frame;
  366. /**/ if (types[1] == 'i')
  367. {
  368. const int32_t i = argv[1]->i;
  369. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(i >= 0);
  370. frame = static_cast<uint64_t>(i);
  371. }
  372. else if (types[1] == 'h')
  373. {
  374. const int64_t h = argv[1]->h;
  375. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(h >= 0);
  376. frame = static_cast<uint64_t>(h);
  377. }
  378. else
  379. {
  380. carla_stderr2("Wrong OSC type used for '%s'", method);
  381. sendResponse(messageId, "Wrong OSC type");
  382. return 0;
  383. }
  384. ok = true;
  385. fEngine->transportRelocate(frame);
  386. }
  387. else if (std::strcmp(method, "add_plugin") == 0)
  388. {
  389. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 8);
  390. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  391. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i');
  392. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[3] == 's');
  393. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[4] == 's');
  394. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[5] == 's');
  395. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[7] == 'i');
  396. int32_t btype = argv[1]->i;
  397. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(btype >= 0);
  398. const int32_t ptype = argv[2]->i;
  399. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(ptype >= 0);
  400. // Force binary type to be native in some cases
  401. switch (ptype)
  402. {
  403. case PLUGIN_INTERNAL:
  404. case PLUGIN_LV2:
  405. case PLUGIN_SF2:
  406. case PLUGIN_SFZ:
  407. case PLUGIN_JACK:
  408. btype = BINARY_NATIVE;
  409. break;
  410. }
  411. const char* filename = &argv[3]->s;
  412. if (filename != nullptr && std::strcmp(filename, "(null)") == 0)
  413. filename = nullptr;
  414. const char* name = &argv[4]->s;
  415. if (name != nullptr && std::strcmp(name, "(null)") == 0)
  416. name = nullptr;
  417. const char* const label = &argv[5]->s;
  418. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(label != nullptr && label[0] != '\0');
  419. int64_t uniqueId;
  420. /**/ if (types[6] == 'i')
  421. {
  422. uniqueId = argv[6]->i;
  423. }
  424. else if (types[6] == 'h')
  425. {
  426. uniqueId = argv[6]->h;
  427. }
  428. else
  429. {
  430. carla_stderr2("Wrong OSC type used for '%s' uniqueId", method);
  431. sendResponse(messageId, "Wrong OSC type");
  432. return 0;
  433. }
  434. const int32_t options = argv[7]->i;
  435. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(options >= 0);
  436. ok = fEngine->addPlugin(static_cast<BinaryType>(btype),
  437. static_cast<PluginType>(ptype),
  438. filename, name, label, uniqueId, nullptr, static_cast<uint32_t>(options));
  439. }
  440. else if (std::strcmp(method, "remove_plugin") == 0)
  441. {
  442. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2);
  443. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  444. const int32_t id = argv[1]->i;
  445. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(id >= 0);
  446. ok = fEngine->removePlugin(static_cast<uint32_t>(id));
  447. }
  448. else if (std::strcmp(method, "remove_all_plugins") == 0)
  449. {
  450. ok = fEngine->removeAllPlugins();
  451. }
  452. else if (std::strcmp(method, "rename_plugin") == 0)
  453. {
  454. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 3);
  455. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  456. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 's');
  457. const int32_t id = argv[1]->i;
  458. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(id >= 0);
  459. const char* const newName = &argv[2]->s;
  460. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(newName != nullptr && newName[0] != '\0');
  461. ok = fEngine->renamePlugin(static_cast<uint32_t>(id), newName);
  462. }
  463. else if (std::strcmp(method, "clone_plugin") == 0)
  464. {
  465. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2);
  466. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  467. const int32_t id = argv[1]->i;
  468. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(id >= 0);
  469. ok = fEngine->clonePlugin(static_cast<uint32_t>(id));
  470. }
  471. else if (std::strcmp(method, "replace_plugin") == 0)
  472. {
  473. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 2);
  474. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  475. const int32_t id = argv[1]->i;
  476. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(id >= 0);
  477. ok = fEngine->replacePlugin(static_cast<uint32_t>(id));
  478. }
  479. else if (std::strcmp(method, "switch_plugins") == 0)
  480. {
  481. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(argc == 3);
  482. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[1] == 'i');
  483. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(types[2] == 'i');
  484. const int32_t idA = argv[1]->i;
  485. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(idA >= 0);
  486. const int32_t idB = argv[2]->i;
  487. CARLA_SAFE_ASSERT_RETURN_OSC_ERR(idB >= 0);
  488. ok = fEngine->switchPlugins(static_cast<uint32_t>(idA), static_cast<uint32_t>(idB));
  489. }
  490. else
  491. {
  492. carla_stderr2("Unhandled OSC control for '%s'", method);
  493. sendResponse(messageId, "Unhandled OSC control method");
  494. return 0;
  495. }
  496. #undef CARLA_SAFE_ASSERT_RETURN_OSC_ERR
  497. sendResponse(messageId, ok ? "" : fEngine->getLastError());
  498. return 0;
  499. }
  500. // -----------------------------------------------------------------------
  501. int CarlaEngineOsc::handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS)
  502. {
  503. carla_debug("CarlaEngineOsc::handleMsgSetActive()");
  504. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  505. const bool active = (argv[0]->i != 0);
  506. plugin->setActive(active, false, true);
  507. return 0;
  508. }
  509. int CarlaEngineOsc::handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS)
  510. {
  511. carla_debug("CarlaEngineOsc::handleMsgSetDryWet()");
  512. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  513. const float value = argv[0]->f;
  514. plugin->setDryWet(value, false, true);
  515. return 0;
  516. }
  517. int CarlaEngineOsc::handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS)
  518. {
  519. carla_debug("CarlaEngineOsc::handleMsgSetVolume()");
  520. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  521. const float value = argv[0]->f;
  522. plugin->setVolume(value, false, true);
  523. return 0;
  524. }
  525. int CarlaEngineOsc::handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS)
  526. {
  527. carla_debug("CarlaEngineOsc::handleMsgSetBalanceLeft()");
  528. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  529. const float value = argv[0]->f;
  530. plugin->setBalanceLeft(value, false, true);
  531. return 0;
  532. }
  533. int CarlaEngineOsc::handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS)
  534. {
  535. carla_debug("CarlaEngineOsc::handleMsgSetBalanceRight()");
  536. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  537. const float value = argv[0]->f;
  538. plugin->setBalanceRight(value, false, true);
  539. return 0;
  540. }
  541. int CarlaEngineOsc::handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS)
  542. {
  543. carla_debug("CarlaEngineOsc::handleMsgSetPanning()");
  544. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  545. const float value = argv[0]->f;
  546. plugin->setPanning(value, false, true);
  547. return 0;
  548. }
  549. int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS)
  550. {
  551. carla_debug("CarlaEngineOsc::handleMsgSetParameterValue()");
  552. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if");
  553. const int32_t index = argv[0]->i;
  554. const float value = argv[1]->f;
  555. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  556. plugin->setParameterValue(static_cast<uint32_t>(index), value, true, false, true);
  557. return 0;
  558. }
  559. int CarlaEngineOsc::handleMsgSetParameterMappedControlIndex(CARLA_ENGINE_OSC_HANDLE_ARGS)
  560. {
  561. carla_debug("CarlaEngineOsc::handleMsgSetParameterMappedIndex()");
  562. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  563. const int32_t index = argv[0]->i;
  564. const int32_t ctrl = argv[1]->i;
  565. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  566. CARLA_SAFE_ASSERT_RETURN(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED, 0);
  567. plugin->setParameterMappedControlIndex(static_cast<uint32_t>(index), static_cast<int16_t>(ctrl), false, true, true);
  568. return 0;
  569. }
  570. int CarlaEngineOsc::handleMsgSetParameterMappedRange(CARLA_ENGINE_OSC_HANDLE_ARGS)
  571. {
  572. carla_debug("CarlaEngineOsc::handleMsgSetParameterMappedRange()");
  573. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "iff");
  574. const int32_t index = argv[0]->i;
  575. const float minimum = argv[1]->f;
  576. const float maximum = argv[2]->f;
  577. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  578. plugin->setParameterMappedRange(static_cast<uint32_t>(index), minimum, maximum, false, true);
  579. return 0;
  580. }
  581. int CarlaEngineOsc::handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS)
  582. {
  583. carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiChannel()");
  584. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  585. const int32_t index = argv[0]->i;
  586. const int32_t channel = argv[1]->i;
  587. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  588. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  589. plugin->setParameterMidiChannel(static_cast<uint32_t>(index), static_cast<uint8_t>(channel), false, true);
  590. return 0;
  591. }
  592. int CarlaEngineOsc::handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS)
  593. {
  594. carla_debug("CarlaEngineOsc::handleMsgSetProgram()");
  595. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  596. const int32_t index = argv[0]->i;
  597. CARLA_SAFE_ASSERT_RETURN(index >= -1, 0);
  598. plugin->setProgram(index, true, false, true);
  599. return 0;
  600. }
  601. int CarlaEngineOsc::handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS)
  602. {
  603. carla_debug("CarlaEngineOsc::handleMsgSetMidiProgram()");
  604. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  605. const int32_t index = argv[0]->i;
  606. CARLA_SAFE_ASSERT_RETURN(index >= -1, 0);
  607. plugin->setMidiProgram(index, true, false, true);
  608. return 0;
  609. }
  610. int CarlaEngineOsc::handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS)
  611. {
  612. carla_debug("CarlaEngineOsc::handleMsgNoteOn()");
  613. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(3, "iii");
  614. const int32_t channel = argv[0]->i;
  615. const int32_t note = argv[1]->i;
  616. const int32_t velo = argv[2]->i;
  617. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  618. CARLA_SAFE_ASSERT_RETURN(note >= 0 && note < MAX_MIDI_NOTE, 0);
  619. CARLA_SAFE_ASSERT_RETURN(velo >= 0 && velo < MAX_MIDI_VALUE, 0);
  620. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), static_cast<uint8_t>(velo), true, false, true);
  621. return 0;
  622. }
  623. int CarlaEngineOsc::handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS)
  624. {
  625. carla_debug("CarlaEngineOsc::handleMsgNoteOff()");
  626. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  627. const int32_t channel = argv[0]->i;
  628. const int32_t note = argv[1]->i;
  629. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  630. CARLA_SAFE_ASSERT_RETURN(note >= 0 && note < MAX_MIDI_NOTE, 0);
  631. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), 0, true, false, true);
  632. return 0;
  633. }
  634. // -----------------------------------------------------------------------
  635. CARLA_BACKEND_END_NAMESPACE
  636. #endif // HAVE_LIBLO