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.

356 lines
12KB

  1. /*
  2. * Carla OSC utils
  3. * Copyright (C) 2012-2013 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 GPL.txt file
  16. */
  17. #ifndef __CARLA_OSC_UTILS_HPP__
  18. #define __CARLA_OSC_UTILS_HPP__
  19. #include "CarlaJuceUtils.hpp"
  20. #include <cstdint>
  21. #include <lo/lo.h>
  22. // -------------------------------------------------
  23. struct CarlaOscData {
  24. const char* path;
  25. lo_address source;
  26. lo_address target;
  27. CarlaOscData()
  28. : path(nullptr),
  29. source(nullptr),
  30. target(nullptr) {}
  31. ~CarlaOscData()
  32. {
  33. free();
  34. }
  35. void free()
  36. {
  37. if (path != nullptr)
  38. {
  39. delete[] path;
  40. path = nullptr;
  41. }
  42. if (source != nullptr)
  43. {
  44. lo_address_free(source);
  45. source = nullptr;
  46. }
  47. if (target != nullptr)
  48. {
  49. lo_address_free(target);
  50. target = nullptr;
  51. }
  52. }
  53. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(CarlaOscData)
  54. };
  55. // -------------------------------------------------
  56. static inline
  57. void osc_send_configure(const CarlaOscData* const oscData, const char* const key, const char* const value)
  58. {
  59. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  60. CARLA_ASSERT(key != nullptr);
  61. CARLA_ASSERT(value != nullptr);
  62. carla_debug("osc_send_configure(path:\"%s\", \"%s\", \"%s\")", oscData->path, key, value);
  63. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && key != nullptr && value != nullptr)
  64. {
  65. char targetPath[std::strlen(oscData->path)+11];
  66. std::strcpy(targetPath, oscData->path);
  67. std::strcat(targetPath, "/configure");
  68. lo_send(oscData->target, targetPath, "ss", key, value);
  69. }
  70. }
  71. static inline
  72. void osc_send_control(const CarlaOscData* const oscData, const int32_t index, const float value)
  73. {
  74. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  75. CARLA_ASSERT(index != -1); // -1 == PARAMETER_NULL
  76. carla_debug("osc_send_control(path:\"%s\", %i, %f)", oscData->path, index, value);
  77. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && index != -1)
  78. {
  79. char targetPath[std::strlen(oscData->path)+9];
  80. std::strcpy(targetPath, oscData->path);
  81. std::strcat(targetPath, "/control");
  82. lo_send(oscData->target, targetPath, "if", index, value);
  83. }
  84. }
  85. static inline
  86. void osc_send_program(const CarlaOscData* const oscData, const int32_t index)
  87. {
  88. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  89. CARLA_ASSERT(index >= 0);
  90. carla_debug("osc_send_program(path:\"%s\", %i)", oscData->path, index);
  91. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && index >= 0)
  92. {
  93. char targetPath[std::strlen(oscData->path)+9];
  94. std::strcpy(targetPath, oscData->path);
  95. std::strcat(targetPath, "/program");
  96. lo_send(oscData->target, targetPath, "i", index);
  97. }
  98. }
  99. static inline
  100. void osc_send_program(const CarlaOscData* const oscData, const int32_t bank, const int32_t program)
  101. {
  102. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  103. CARLA_ASSERT(program >= 0);
  104. CARLA_ASSERT(bank >= 0);
  105. carla_debug("osc_send_program(path:\"%s\", %i, %i)", oscData->path, bank, program);
  106. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && bank >= 0 && program >= 0)
  107. {
  108. char targetPath[std::strlen(oscData->path)+9];
  109. std::strcpy(targetPath, oscData->path);
  110. std::strcat(targetPath, "/program");
  111. lo_send(oscData->target, targetPath, "ii", bank, program);
  112. }
  113. }
  114. static inline
  115. void osc_send_midi_program(const CarlaOscData* const oscData, const int32_t index)
  116. {
  117. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  118. CARLA_ASSERT(index >= 0);
  119. carla_debug("osc_send_midi_program(path:\"%s\", %i)", oscData->path, index);
  120. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && index >= 0)
  121. {
  122. char targetPath[std::strlen(oscData->path)+14];
  123. std::strcpy(targetPath, oscData->path);
  124. std::strcat(targetPath, "/midi-program");
  125. lo_send(oscData->target, targetPath, "i", index);
  126. }
  127. }
  128. static inline
  129. void osc_send_midi_program(const CarlaOscData* const oscData, const int32_t bank, const int32_t program)
  130. {
  131. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  132. CARLA_ASSERT(program >= 0);
  133. CARLA_ASSERT(bank >= 0);
  134. carla_debug("osc_send_midi_program(path:\"%s\", %i, %i)", oscData->path, bank, program);
  135. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && bank >= 0 && program >= 0)
  136. {
  137. char targetPath[std::strlen(oscData->path)+14];
  138. std::strcpy(targetPath, oscData->path);
  139. std::strcat(targetPath, "/midi-program");
  140. lo_send(oscData->target, targetPath, "ii", bank, program);
  141. }
  142. }
  143. static inline
  144. void osc_send_midi(const CarlaOscData* const oscData, const uint8_t buf[4])
  145. {
  146. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  147. CARLA_ASSERT(buf[0] == 0);
  148. CARLA_ASSERT(buf[1] != 0);
  149. carla_debug("osc_send_midi(path:\"%s\", 0x%X, %03u, %03u)", oscData->path, buf[1], buf[2], buf[3]);
  150. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && buf[0] == 0 && buf[1] != 0)
  151. {
  152. char targetPath[std::strlen(oscData->path)+6];
  153. std::strcpy(targetPath, oscData->path);
  154. std::strcat(targetPath, "/midi");
  155. lo_send(oscData->target, targetPath, "m", buf);
  156. }
  157. }
  158. static inline
  159. void osc_send_sample_rate(const CarlaOscData* const oscData, const float sampleRate)
  160. {
  161. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  162. CARLA_ASSERT(sampleRate > 0.0f);
  163. carla_debug("osc_send_sample_rate(path:\"%s\", %f)", oscData->path, sampleRate);
  164. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && sampleRate > 0.0f)
  165. {
  166. char targetPath[std::strlen(oscData->path)+13];
  167. std::strcpy(targetPath, oscData->path);
  168. std::strcat(targetPath, "/sample-rate");
  169. lo_send(oscData->target, targetPath, "f", sampleRate);
  170. }
  171. }
  172. #ifdef BUILD_BRIDGE
  173. static inline
  174. void osc_send_update(const CarlaOscData* const oscData, const char* const url)
  175. {
  176. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  177. CARLA_ASSERT(url != nullptr);
  178. carla_debug("osc_send_update(path:\"%s\", \"%s\")", oscData->path, url);
  179. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && url != nullptr)
  180. {
  181. char targetPath[std::strlen(oscData->path)+8];
  182. std::strcpy(targetPath, oscData->path);
  183. std::strcat(targetPath, "/update");
  184. lo_send(oscData->target, targetPath, "s", url);
  185. }
  186. }
  187. static inline
  188. void osc_send_exiting(const CarlaOscData* const oscData)
  189. {
  190. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  191. carla_debug("osc_send_exiting(path:\"%s\")", oscData->path);
  192. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr)
  193. {
  194. char targetPath[std::strlen(oscData->path)+9];
  195. std::strcpy(targetPath, oscData->path);
  196. std::strcat(targetPath, "/exiting");
  197. lo_send(oscData->target, targetPath, "");
  198. }
  199. }
  200. #endif
  201. static inline
  202. void osc_send_show(const CarlaOscData* const oscData)
  203. {
  204. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  205. carla_debug("osc_send_show(path:\"%s\")", oscData->path);
  206. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr)
  207. {
  208. char targetPath[std::strlen(oscData->path)+6];
  209. std::strcpy(targetPath, oscData->path);
  210. std::strcat(targetPath, "/show");
  211. lo_send(oscData->target, targetPath, "");
  212. }
  213. }
  214. static inline
  215. void osc_send_hide(const CarlaOscData* const oscData)
  216. {
  217. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  218. carla_debug("osc_send_hide(path:\"%s\")", oscData->path);
  219. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr)
  220. {
  221. char targetPath[std::strlen(oscData->path)+6];
  222. std::strcpy(targetPath, oscData->path);
  223. std::strcat(targetPath, "/hide");
  224. lo_send(oscData->target, targetPath, "");
  225. }
  226. }
  227. static inline
  228. void osc_send_quit(const CarlaOscData* const oscData)
  229. {
  230. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  231. carla_debug("osc_send_quit(path:\"%s\")", oscData->path);
  232. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr)
  233. {
  234. char targetPath[std::strlen(oscData->path)+6];
  235. std::strcpy(targetPath, oscData->path);
  236. std::strcat(targetPath, "/quit");
  237. lo_send(oscData->target, targetPath, "");
  238. }
  239. }
  240. // -------------------------------------------------
  241. #ifdef BUILD_BRIDGE_PLUGIN
  242. static inline
  243. void osc_send_bridge_update(const CarlaOscData* const oscData, const char* const url)
  244. {
  245. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  246. CARLA_ASSERT(url != nullptr);
  247. carla_debug("osc_send_bridge_update(path:\"%s\", \"%s\")", oscData->path, url);
  248. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && url != nullptr)
  249. {
  250. char targetPath[std::strlen(oscData->path)+15];
  251. std::strcpy(targetPath, oscData->path);
  252. std::strcat(targetPath, "/bridge_update");
  253. lo_send(oscData->target, targetPath, "s", url);
  254. }
  255. }
  256. static inline
  257. void osc_send_bridge_error(const CarlaOscData* const oscData, const char* const error)
  258. {
  259. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  260. CARLA_ASSERT(error != nullptr);
  261. carla_debug("osc_send_bridge_error(path:\"%s\", \"%s\")", oscData->path, error);
  262. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && error != nullptr)
  263. {
  264. char targetPath[std::strlen(oscData->path)+14];
  265. std::strcpy(targetPath, oscData->path);
  266. std::strcat(targetPath, "/bridge_error");
  267. lo_send(oscData->target, targetPath, "s", error);
  268. }
  269. }
  270. #endif
  271. #if defined(BRIDGE_LV2) || defined(WANT_LV2)
  272. static inline
  273. void osc_send_lv2_transfer_atom(const CarlaOscData* const oscData, const int32_t portIndex, const char* const typeStr, const char* const atomBuf)
  274. {
  275. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  276. CARLA_ASSERT(portIndex >= 0);
  277. CARLA_ASSERT(typeStr != nullptr);
  278. CARLA_ASSERT(atomBuf != nullptr);
  279. carla_debug("osc_send_lv2_transfer_atom(path:\"%s\", %i, \"%s\", <atomBuf:%p>)", oscData->path, portIndex, typeStr, atomBuf);
  280. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && portIndex >= 0 && typeStr != nullptr && atomBuf != nullptr)
  281. {
  282. char targetPath[std::strlen(oscData->path)+19];
  283. std::strcpy(targetPath, oscData->path);
  284. std::strcat(targetPath, "/lv2_atom_transfer");
  285. lo_send(oscData->target, targetPath, "iss", portIndex, typeStr, atomBuf);
  286. }
  287. }
  288. static inline
  289. void osc_send_lv2_transfer_event(const CarlaOscData* const oscData, const int32_t portIndex, const char* const typeStr, const char* const atomBuf)
  290. {
  291. CARLA_ASSERT(oscData != nullptr && oscData->path != nullptr);
  292. CARLA_ASSERT(portIndex >= 0);
  293. CARLA_ASSERT(typeStr != nullptr);
  294. CARLA_ASSERT(atomBuf != nullptr);
  295. carla_debug("osc_send_lv2_transfer_event(path:\"%s\", %i, \"%s\", <atomBuf:%p>)", oscData->path, portIndex, typeStr, atomBuf);
  296. if (oscData != nullptr && oscData->path != nullptr && oscData->target != nullptr && portIndex >= 0 && typeStr != nullptr && atomBuf != nullptr)
  297. {
  298. char targetPath[std::strlen(oscData->path)+20];
  299. std::strcpy(targetPath, oscData->path);
  300. std::strcat(targetPath, "/lv2_event_transfer");
  301. lo_send(oscData->target, targetPath, "iss", portIndex, typeStr, atomBuf);
  302. }
  303. }
  304. #endif
  305. // -------------------------------------------------
  306. #endif // __CARLA_OSC_UTILS_HPP__