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.

CarlaEngineOsc.cpp 26KB

11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  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. #ifndef BUILD_BRIDGE
  21. # include "CarlaBridgeUtils.hpp"
  22. #endif
  23. #include "CarlaMIDI.h"
  24. #include <cctype>
  25. CARLA_BACKEND_START_NAMESPACE
  26. #ifndef BUILD_BRIDGE
  27. // -------------------------------------------------------------------
  28. // Bridge Helper, defined in BridgePlugin.cpp
  29. extern int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeOscInfoType type,
  30. const int argc, const lo_arg* const* const argv, const char* const types);
  31. #endif
  32. // -----------------------------------------------------------------------
  33. CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine) noexcept
  34. : fEngine(engine),
  35. #ifndef BUILD_BRIDGE
  36. fControlData(),
  37. #endif
  38. fName(),
  39. fServerPathTCP(),
  40. fServerPathUDP(),
  41. fServerTCP(nullptr),
  42. fServerUDP(nullptr),
  43. leakDetector_CarlaEngineOsc()
  44. {
  45. CARLA_SAFE_ASSERT(engine != nullptr);
  46. carla_debug("CarlaEngineOsc::CarlaEngineOsc(%p)", engine);
  47. }
  48. CarlaEngineOsc::~CarlaEngineOsc() noexcept
  49. {
  50. CARLA_SAFE_ASSERT(fName.isEmpty());
  51. CARLA_SAFE_ASSERT(fServerPathTCP.isEmpty());
  52. CARLA_SAFE_ASSERT(fServerPathUDP.isEmpty());
  53. CARLA_SAFE_ASSERT(fServerTCP == nullptr);
  54. CARLA_SAFE_ASSERT(fServerUDP == nullptr);
  55. carla_debug("CarlaEngineOsc::~CarlaEngineOsc()");
  56. }
  57. // -----------------------------------------------------------------------
  58. void CarlaEngineOsc::init(const char* const name) noexcept
  59. {
  60. CARLA_SAFE_ASSERT_RETURN(fName.isEmpty(),);
  61. CARLA_SAFE_ASSERT_RETURN(fServerPathTCP.isEmpty(),);
  62. CARLA_SAFE_ASSERT_RETURN(fServerPathUDP.isEmpty(),);
  63. CARLA_SAFE_ASSERT_RETURN(fServerTCP == nullptr,);
  64. CARLA_SAFE_ASSERT_RETURN(fServerUDP == nullptr,);
  65. CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
  66. carla_debug("CarlaEngineOsc::init(\"%s\")", name);
  67. fName = name;
  68. fName.toBasic();
  69. fServerTCP = lo_server_new_with_proto(nullptr, LO_TCP, osc_error_handler_TCP);
  70. if (fServerTCP != nullptr)
  71. {
  72. if (char* const tmpServerPathTCP = lo_server_get_url(fServerTCP))
  73. {
  74. fServerPathTCP = tmpServerPathTCP;
  75. fServerPathTCP += fName;
  76. std::free(tmpServerPathTCP);
  77. }
  78. lo_server_add_method(fServerTCP, nullptr, nullptr, osc_message_handler_TCP, this);
  79. }
  80. fServerUDP = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler_UDP);
  81. if (fServerUDP != nullptr)
  82. {
  83. if (char* const tmpServerPathUDP = lo_server_get_url(fServerUDP))
  84. {
  85. fServerPathUDP = tmpServerPathUDP;
  86. fServerPathUDP += fName;
  87. std::free(tmpServerPathUDP);
  88. }
  89. lo_server_add_method(fServerUDP, nullptr, nullptr, osc_message_handler_UDP, this);
  90. }
  91. CARLA_SAFE_ASSERT(fName.isNotEmpty());
  92. CARLA_SAFE_ASSERT(fServerPathTCP.isNotEmpty());
  93. CARLA_SAFE_ASSERT(fServerPathUDP.isNotEmpty());
  94. CARLA_SAFE_ASSERT(fServerTCP != nullptr);
  95. CARLA_SAFE_ASSERT(fServerUDP != nullptr);
  96. }
  97. void CarlaEngineOsc::idle() const noexcept
  98. {
  99. if (fServerTCP != nullptr)
  100. {
  101. for (;;)
  102. {
  103. try {
  104. if (lo_server_recv_noblock(fServerTCP, 0) == 0)
  105. break;
  106. } CARLA_SAFE_EXCEPTION_CONTINUE("OSC idle TCP")
  107. }
  108. }
  109. if (fServerUDP != nullptr)
  110. {
  111. for (;;)
  112. {
  113. try {
  114. if (lo_server_recv_noblock(fServerUDP, 0) == 0)
  115. break;
  116. } CARLA_SAFE_EXCEPTION_CONTINUE("OSC idle UDP")
  117. }
  118. }
  119. }
  120. void CarlaEngineOsc::close() noexcept
  121. {
  122. CARLA_SAFE_ASSERT(fName.isNotEmpty());
  123. CARLA_SAFE_ASSERT(fServerPathTCP.isNotEmpty());
  124. CARLA_SAFE_ASSERT(fServerPathUDP.isNotEmpty());
  125. CARLA_SAFE_ASSERT(fServerTCP != nullptr);
  126. CARLA_SAFE_ASSERT(fServerUDP != nullptr);
  127. carla_debug("CarlaEngineOsc::close()");
  128. fName.clear();
  129. if (fServerTCP != nullptr)
  130. {
  131. lo_server_del_method(fServerTCP, nullptr, nullptr);
  132. lo_server_free(fServerTCP);
  133. fServerTCP = nullptr;
  134. }
  135. if (fServerUDP != nullptr)
  136. {
  137. lo_server_del_method(fServerUDP, nullptr, nullptr);
  138. lo_server_free(fServerUDP);
  139. fServerUDP = nullptr;
  140. }
  141. fServerPathTCP.clear();
  142. fServerPathUDP.clear();
  143. #ifndef BUILD_BRIDGE
  144. fControlData.clear();
  145. #endif
  146. }
  147. // -----------------------------------------------------------------------
  148. 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)
  149. {
  150. CARLA_SAFE_ASSERT_RETURN(fName.isNotEmpty(), 1);
  151. CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', 1);
  152. #ifdef DEBUG
  153. if (std::strstr(path, "/bridge_pong") == nullptr) {
  154. carla_debug("CarlaEngineOsc::handleMessage(%s, \"%s\", %i, %p, \"%s\", %p)", bool2str(isTCP), path, argc, argv, types, msg);
  155. }
  156. #endif
  157. //if (isTCP)
  158. {
  159. CARLA_SAFE_ASSERT_RETURN(fServerPathTCP.isNotEmpty(), 1);
  160. CARLA_SAFE_ASSERT_RETURN(fServerTCP != nullptr, 1);
  161. }
  162. //else
  163. {
  164. CARLA_SAFE_ASSERT_RETURN(fServerPathUDP.isNotEmpty(), 1);
  165. CARLA_SAFE_ASSERT_RETURN(fServerUDP != nullptr, 1);
  166. }
  167. #ifndef BUILD_BRIDGE
  168. // Initial path check
  169. if (std::strcmp(path, "/register") == 0)
  170. {
  171. const lo_address source(lo_message_get_source(msg));
  172. return handleMsgRegister(isTCP, argc, argv, types, source);
  173. }
  174. if (std::strcmp(path, "/unregister") == 0)
  175. {
  176. return handleMsgUnregister();
  177. }
  178. #endif
  179. const size_t nameSize(fName.length());
  180. // Check if message is for this client
  181. if (std::strlen(path) <= nameSize || std::strncmp(path+1, fName, nameSize) != 0)
  182. {
  183. carla_stderr("CarlaEngineOsc::handleMessage() - message not for this client -> '%s' != '/%s/'", path, fName.buffer());
  184. return 1;
  185. }
  186. // Get plugin id from path, "/carla/23/method" -> 23
  187. uint pluginId = 0;
  188. size_t offset;
  189. if (std::isdigit(path[nameSize+2]))
  190. {
  191. if (std::isdigit(path[nameSize+3]))
  192. {
  193. if (std::isdigit(path[nameSize+5]))
  194. {
  195. carla_stderr2("CarlaEngineOsc::handleMessage() - invalid plugin id, over 999? (value: \"%s\")", path+(nameSize+1));
  196. return 1;
  197. }
  198. else if (std::isdigit(path[nameSize+4]))
  199. {
  200. // 3 digits, /xyz/method
  201. offset = 6;
  202. pluginId += uint(path[nameSize+2]-'0')*100;
  203. pluginId += uint(path[nameSize+3]-'0')*10;
  204. pluginId += uint(path[nameSize+4]-'0');
  205. }
  206. else
  207. {
  208. // 2 digits, /xy/method
  209. offset = 5;
  210. pluginId += uint(path[nameSize+2]-'0')*10;
  211. pluginId += uint(path[nameSize+3]-'0');
  212. }
  213. }
  214. else
  215. {
  216. // single digit, /x/method
  217. offset = 4;
  218. pluginId += uint(path[nameSize+2]-'0');
  219. }
  220. }
  221. else
  222. {
  223. carla_stderr("CarlaEngineOsc::handleMessage() - invalid message '%s'", path);
  224. return 1;
  225. }
  226. if (pluginId > fEngine->getCurrentPluginCount())
  227. {
  228. carla_stderr("CarlaEngineOsc::handleMessage() - failed to get plugin, wrong id '%i'", pluginId);
  229. return 0;
  230. }
  231. // Get plugin
  232. CarlaPlugin* const plugin(fEngine->getPluginUnchecked(pluginId));
  233. if (plugin == nullptr || plugin->getId() != pluginId)
  234. {
  235. carla_stderr("CarlaEngineOsc::handleMessage() - invalid plugin id '%i', probably has been removed (path: '%s')", pluginId, path);
  236. return 0;
  237. }
  238. // Get method from path, "/Carla/i/method" -> "method"
  239. char method[32+1];
  240. method[32] = '\0';
  241. std::strncpy(method, path + (nameSize + offset), 32);
  242. if (method[0] == '\0')
  243. {
  244. carla_stderr("CarlaEngineOsc::handleMessage(%s, \"%s\", ...) - received message without method", bool2str(isTCP), path);
  245. return 0;
  246. }
  247. // Common OSC methods (all bridges)
  248. if (std::strcmp(method, "update") == 0)
  249. {
  250. const lo_address source(lo_message_get_source(msg));
  251. return handleMsgUpdate(plugin, argc, argv, types, source);
  252. }
  253. if (std::strcmp(method, "exiting") == 0)
  254. return handleMsgExiting(plugin);
  255. #ifndef BUILD_BRIDGE
  256. // Common OSC methods (DSSI and bridge UIs)
  257. if (std::strcmp(method, "configure") == 0)
  258. return handleMsgConfigure(plugin, argc, argv, types);
  259. if (std::strcmp(method, "control") == 0)
  260. return handleMsgControl(plugin, argc, argv, types);
  261. if (std::strcmp(method, "program") == 0)
  262. return handleMsgProgram(plugin, argc, argv, types);
  263. if (std::strcmp(method, "midi") == 0)
  264. return handleMsgMidi(plugin, argc, argv, types);
  265. // Internal methods
  266. if (std::strcmp(method, "set_active") == 0)
  267. return handleMsgSetActive(plugin, argc, argv, types);
  268. if (std::strcmp(method, "set_drywet") == 0)
  269. return handleMsgSetDryWet(plugin, argc, argv, types);
  270. if (std::strcmp(method, "set_volume") == 0)
  271. return handleMsgSetVolume(plugin, argc, argv, types);
  272. if (std::strcmp(method, "set_balance_left") == 0)
  273. return handleMsgSetBalanceLeft(plugin, argc, argv, types);
  274. if (std::strcmp(method, "set_balance_right") == 0)
  275. return handleMsgSetBalanceRight(plugin, argc, argv, types);
  276. if (std::strcmp(method, "set_panning") == 0)
  277. return handleMsgSetPanning(plugin, argc, argv, types);
  278. if (std::strcmp(method, "set_parameter_value") == 0)
  279. return handleMsgSetParameterValue(plugin, argc, argv, types);
  280. if (std::strcmp(method, "set_parameter_midi_cc") == 0)
  281. return handleMsgSetParameterMidiCC(plugin, argc, argv, types);
  282. if (std::strcmp(method, "set_parameter_midi_channel") == 0)
  283. return handleMsgSetParameterMidiChannel(plugin, argc, argv, types);
  284. if (std::strcmp(method, "set_program") == 0)
  285. return handleMsgSetProgram(plugin, argc, argv, types);
  286. if (std::strcmp(method, "set_midi_program") == 0)
  287. return handleMsgSetMidiProgram(plugin, argc, argv, types);
  288. if (std::strcmp(method, "note_on") == 0)
  289. return handleMsgNoteOn(plugin, argc, argv, types);
  290. if (std::strcmp(method, "note_off") == 0)
  291. return handleMsgNoteOff(plugin, argc, argv, types);
  292. // Plugin Bridges
  293. if ((plugin->getHints() & PLUGIN_IS_BRIDGE) != 0 && std::strlen(method) >= 11 && std::strncmp(method, "bridge_", 7) == 0)
  294. {
  295. const char* const bmethod(method+7);
  296. if (std::strcmp(bmethod, "pong") == 0)
  297. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscPong, argc, argv, types);
  298. if (std::strcmp(bmethod, "plugin_info1") == 0)
  299. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscPluginInfo1, argc, argv, types);
  300. if (std::strcmp(bmethod, "plugin_info2") == 0)
  301. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscPluginInfo2, argc, argv, types);
  302. if (std::strcmp(bmethod, "audio_count") == 0)
  303. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscAudioCount, argc, argv, types);
  304. if (std::strcmp(bmethod, "midi_count") == 0)
  305. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscMidiCount, argc, argv, types);
  306. if (std::strcmp(bmethod, "parameter_count") == 0)
  307. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterCount, argc, argv, types);
  308. if (std::strcmp(bmethod, "program_count") == 0)
  309. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscProgramCount, argc, argv, types);
  310. if (std::strcmp(bmethod, "midi_program_count") == 0)
  311. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscMidiProgramCount, argc, argv, types);
  312. if (std::strcmp(bmethod, "parameter_data1") == 0)
  313. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterData1, argc, argv, types);
  314. if (std::strcmp(bmethod, "parameter_data2") == 0)
  315. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterData2, argc, argv, types);
  316. if (std::strcmp(bmethod, "parameter_ranges1") == 0)
  317. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterRanges1, argc, argv, types);
  318. if (std::strcmp(bmethod, "parameter_ranges2") == 0)
  319. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterRanges2, argc, argv, types);
  320. if (std::strcmp(bmethod, "parameter_value") == 0)
  321. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterValue, argc, argv, types);
  322. if (std::strcmp(bmethod, "default_value") == 0)
  323. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscDefaultValue, argc, argv, types);
  324. if (std::strcmp(bmethod, "current_program") == 0)
  325. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscCurrentProgram, argc, argv, types);
  326. if (std::strcmp(bmethod, "current_midi_program") == 0)
  327. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscCurrentMidiProgram, argc, argv, types);
  328. if (std::strcmp(bmethod, "program_name") == 0)
  329. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscProgramName, argc, argv, types);
  330. if (std::strcmp(bmethod, "midi_program_data") == 0)
  331. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscMidiProgramData, argc, argv, types);
  332. if (std::strcmp(bmethod, "configure") == 0)
  333. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscConfigure, argc, argv, types);
  334. if (std::strcmp(bmethod, "set_custom_data") == 0)
  335. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscSetCustomData, argc, argv, types);
  336. if (std::strcmp(bmethod, "set_chunk_data_file") == 0)
  337. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscSetChunkDataFile, argc, argv, types);
  338. if (std::strcmp(bmethod, "latency") == 0)
  339. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscLatency, argc, argv, types);
  340. if (std::strcmp(bmethod, "ready") == 0)
  341. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscReady, argc, argv, types);
  342. if (std::strcmp(bmethod, "error") == 0)
  343. return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscError, argc, argv, types);
  344. }
  345. // Plugin-specific methods
  346. if (std::strcmp(method, "lv2_atom_transfer") == 0)
  347. return handleMsgLv2AtomTransfer(plugin, argc, argv, types);
  348. if (std::strcmp(method, "lv2_urid_map") == 0)
  349. return handleMsgLv2UridMap(plugin, argc, argv, types);
  350. #endif
  351. carla_stderr("CarlaEngineOsc::handleMessage() - unsupported OSC method '%s'", method);
  352. return 1;
  353. }
  354. // -----------------------------------------------------------------------
  355. int CarlaEngineOsc::handleMsgUpdate(CARLA_ENGINE_OSC_HANDLE_ARGS2, const lo_address source)
  356. {
  357. carla_debug("CarlaEngineOsc::handleMsgUpdate()");
  358. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s");
  359. const char* const url = (const char*)&argv[0]->s;
  360. plugin->updateOscData(source, url);
  361. return 0;
  362. }
  363. int CarlaEngineOsc::handleMsgExiting(CARLA_ENGINE_OSC_HANDLE_ARGS1)
  364. {
  365. carla_debug("CarlaEngineOsc::handleMsgExiting()");
  366. // TODO - check for non-UIs (dssi-vst) and set to -1 instead
  367. fEngine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, plugin->getId(), 0, 0, 0.0f, nullptr);
  368. plugin->showCustomUI(false);
  369. return 0;
  370. }
  371. // -----------------------------------------------------------------------
  372. #ifndef BUILD_BRIDGE
  373. int CarlaEngineOsc::handleMsgRegister(const bool isTCP, const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source)
  374. {
  375. carla_debug("CarlaEngineOsc::handleMsgRegister()");
  376. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s");
  377. if (fControlData.path != nullptr)
  378. {
  379. carla_stderr("CarlaEngineOsc::handleMsgRegister() - OSC backend already registered to %s", fControlData.path);
  380. return 1;
  381. }
  382. const char* const url = &argv[0]->s;
  383. carla_debug("CarlaEngineOsc::handleMsgRegister() - OSC backend registered to %s", url);
  384. {
  385. const char* host = lo_address_get_hostname(source);
  386. const char* port = lo_address_get_port(source);
  387. fControlData.source = lo_address_new_with_proto(isTCP ? LO_TCP : LO_UDP, host, port);
  388. }
  389. {
  390. char* host = lo_url_get_hostname(url);
  391. char* port = lo_url_get_port(url);
  392. fControlData.path = carla_strdup_free(lo_url_get_path(url));
  393. fControlData.target = lo_address_new_with_proto(isTCP ? LO_TCP : LO_UDP, host, port);
  394. std::free(host);
  395. std::free(port);
  396. }
  397. for (uint i=0, count=fEngine->getCurrentPluginCount(); i < count; ++i)
  398. {
  399. CarlaPlugin* const plugin(fEngine->getPluginUnchecked(i));
  400. if (plugin != nullptr && plugin->isEnabled())
  401. plugin->registerToOscClient();
  402. }
  403. return 0;
  404. }
  405. int CarlaEngineOsc::handleMsgUnregister()
  406. {
  407. carla_debug("CarlaEngineOsc::handleMsgUnregister()");
  408. if (fControlData.path == nullptr)
  409. {
  410. carla_stderr("CarlaEngineOsc::handleMsgUnregister() - OSC backend is not registered yet");
  411. return 1;
  412. }
  413. fControlData.clear();
  414. return 0;
  415. }
  416. // -----------------------------------------------------------------------
  417. int CarlaEngineOsc::handleMsgConfigure(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  418. {
  419. carla_debug("CarlaEngineOsc::handleMsgConfigure()");
  420. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ss");
  421. const char* const key = (const char*)&argv[0]->s;
  422. const char* const value = (const char*)&argv[1]->s;
  423. plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false);
  424. return 0;
  425. }
  426. int CarlaEngineOsc::handleMsgControl(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  427. {
  428. carla_debug("CarlaEngineOsc::handleMsgControl()");
  429. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if");
  430. const int32_t rindex = argv[0]->i;
  431. const float value = argv[1]->f;
  432. plugin->setParameterValueByRealIndex(rindex, value, false, true, true);
  433. return 0;
  434. }
  435. int CarlaEngineOsc::handleMsgProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  436. {
  437. carla_debug("CarlaEngineOsc::handleMsgProgram()");
  438. if (argc == 2)
  439. {
  440. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  441. const int32_t bank = argv[0]->i;
  442. const int32_t program = argv[1]->i;
  443. CARLA_SAFE_ASSERT_RETURN(bank >= 0, 0);
  444. CARLA_SAFE_ASSERT_RETURN(program >= 0, 0);
  445. plugin->setMidiProgramById(static_cast<uint32_t>(bank), static_cast<uint32_t>(program), false, true, true);
  446. return 0;
  447. }
  448. else
  449. {
  450. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  451. const int32_t program = argv[0]->i;
  452. CARLA_SAFE_ASSERT_RETURN(program >= 0, 0);
  453. CARLA_SAFE_ASSERT_RETURN(program < static_cast<int32_t>(plugin->getProgramCount()), 0);
  454. plugin->setProgram(program, false, true, true);
  455. return 0;
  456. }
  457. }
  458. int CarlaEngineOsc::handleMsgMidi(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  459. {
  460. carla_debug("CarlaEngineOsc::handleMsgMidi()");
  461. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "m");
  462. #ifdef BUILD_BRIDGE
  463. CARLA_ASSERT(false); // this should never happen
  464. return 0;
  465. // unused
  466. (void)plugin;
  467. (void)argv;
  468. #else
  469. if (plugin->getMidiInCount() == 0)
  470. {
  471. carla_stderr("CarlaEngineOsc::handleMsgMidi() - received midi when plugin has no midi inputs");
  472. return 0;
  473. }
  474. const uint8_t* const data = argv[0]->m;
  475. uint8_t status = data[1];
  476. uint8_t channel = status & 0x0F;
  477. // Fix bad note-off
  478. if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0)
  479. status = MIDI_STATUS_NOTE_OFF;
  480. if (MIDI_IS_STATUS_NOTE_OFF(status))
  481. {
  482. const uint8_t note = data[2];
  483. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE, 0);
  484. plugin->sendMidiSingleNote(channel, note, 0, false, true, true);
  485. }
  486. else if (MIDI_IS_STATUS_NOTE_ON(status))
  487. {
  488. const uint8_t note = data[2];
  489. const uint8_t velo = data[3];
  490. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE, 0);
  491. CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE, 0);
  492. plugin->sendMidiSingleNote(channel, note, velo, false, true, true);
  493. }
  494. return 0;
  495. #endif
  496. }
  497. // -----------------------------------------------------------------------
  498. int CarlaEngineOsc::handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  499. {
  500. carla_debug("CarlaEngineOsc::handleMsgSetActive()");
  501. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  502. const bool active = (argv[0]->i != 0);
  503. plugin->setActive(active, false, true);
  504. return 0;
  505. }
  506. int CarlaEngineOsc::handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  507. {
  508. carla_debug("CarlaEngineOsc::handleMsgSetDryWet()");
  509. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  510. const float value = argv[0]->f;
  511. plugin->setDryWet(value, false, true);
  512. return 0;
  513. }
  514. int CarlaEngineOsc::handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  515. {
  516. carla_debug("CarlaEngineOsc::handleMsgSetVolume()");
  517. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  518. const float value = argv[0]->f;
  519. plugin->setVolume(value, false, true);
  520. return 0;
  521. }
  522. int CarlaEngineOsc::handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  523. {
  524. carla_debug("CarlaEngineOsc::handleMsgSetBalanceLeft()");
  525. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  526. const float value = argv[0]->f;
  527. plugin->setBalanceLeft(value, false, true);
  528. return 0;
  529. }
  530. int CarlaEngineOsc::handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  531. {
  532. carla_debug("CarlaEngineOsc::handleMsgSetBalanceRight()");
  533. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  534. const float value = argv[0]->f;
  535. plugin->setBalanceRight(value, false, true);
  536. return 0;
  537. }
  538. int CarlaEngineOsc::handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  539. {
  540. carla_debug("CarlaEngineOsc::handleMsgSetPanning()");
  541. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f");
  542. const float value = argv[0]->f;
  543. plugin->setPanning(value, false, true);
  544. return 0;
  545. }
  546. int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  547. {
  548. carla_debug("CarlaEngineOsc::handleMsgSetParameterValue()");
  549. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if");
  550. const int32_t index = argv[0]->i;
  551. const float value = argv[1]->f;
  552. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  553. plugin->setParameterValue(static_cast<uint32_t>(index), value, true, false, true);
  554. return 0;
  555. }
  556. int CarlaEngineOsc::handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  557. {
  558. carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiCC()");
  559. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  560. const int32_t index = argv[0]->i;
  561. const int32_t cc = argv[1]->i;
  562. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  563. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc <= 0x5F, 0);
  564. plugin->setParameterMidiCC(static_cast<uint32_t>(index), static_cast<int16_t>(cc), false, true);
  565. return 0;
  566. }
  567. int CarlaEngineOsc::handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  568. {
  569. carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiChannel()");
  570. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  571. const int32_t index = argv[0]->i;
  572. const int32_t channel = argv[1]->i;
  573. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  574. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  575. plugin->setParameterMidiChannel(static_cast<uint32_t>(index), static_cast<uint8_t>(channel), false, true);
  576. return 0;
  577. }
  578. int CarlaEngineOsc::handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  579. {
  580. carla_debug("CarlaEngineOsc::handleMsgSetProgram()");
  581. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  582. const int32_t index = argv[0]->i;
  583. CARLA_SAFE_ASSERT_RETURN(index >= -1, 0);
  584. plugin->setProgram(index, true, false, true);
  585. return 0;
  586. }
  587. int CarlaEngineOsc::handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  588. {
  589. carla_debug("CarlaEngineOsc::handleMsgSetMidiProgram()");
  590. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i");
  591. const int32_t index = argv[0]->i;
  592. CARLA_SAFE_ASSERT_RETURN(index >= -1, 0);
  593. plugin->setMidiProgram(index, true, false, true);
  594. return 0;
  595. }
  596. int CarlaEngineOsc::handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  597. {
  598. carla_debug("CarlaEngineOsc::handleMsgNoteOn()");
  599. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(3, "iii");
  600. const int32_t channel = argv[0]->i;
  601. const int32_t note = argv[1]->i;
  602. const int32_t velo = argv[2]->i;
  603. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  604. CARLA_SAFE_ASSERT_RETURN(note >= 0 && note < MAX_MIDI_NOTE, 0);
  605. CARLA_SAFE_ASSERT_RETURN(velo >= 0 && velo < MAX_MIDI_VALUE, 0);
  606. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), static_cast<uint8_t>(velo), true, false, true);
  607. return 0;
  608. }
  609. int CarlaEngineOsc::handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS2)
  610. {
  611. carla_debug("CarlaEngineOsc::handleMsgNoteOff()");
  612. CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii");
  613. const int32_t channel = argv[0]->i;
  614. const int32_t note = argv[1]->i;
  615. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  616. CARLA_SAFE_ASSERT_RETURN(note >= 0 && note < MAX_MIDI_NOTE, 0);
  617. plugin->sendMidiSingleNote(static_cast<uint8_t>(channel), static_cast<uint8_t>(note), 0, true, false, true);
  618. return 0;
  619. }
  620. #endif // ! BUILD_BRIDGE
  621. // -----------------------------------------------------------------------
  622. CARLA_BACKEND_END_NAMESPACE