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.

353 lines
13KB

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