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.

345 lines
12KB

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