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.

357 lines
13KB

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