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.

404 lines
12KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2012 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. #include "Client.H"
  19. #include <string.h>
  20. #include <sys/types.h>
  21. #include <unistd.h>
  22. #include <stdlib.h>
  23. #pragma GCC diagnostic ignored "-Wunused-parameter"
  24. namespace NSM
  25. {
  26. /************************/
  27. /* OSC Message Handlers */
  28. /************************/
  29. #undef OSC_REPLY
  30. #undef OSC_REPLY_ERR
  31. #define OSC_REPLY(value) lo_send_from(((NSM::Client *)user_data)->nsm_addr, \
  32. ((NSM::Client *)user_data)->_server, \
  33. LO_TT_IMMEDIATE, \
  34. "/reply", \
  35. "ss", \
  36. path, \
  37. value)
  38. #define OSC_REPLY_ERR(errcode, value) lo_send_from( \
  39. ((NSM::Client *)user_data)->nsm_addr, \
  40. ((NSM::Client *)user_data)->_server, \
  41. LO_TT_IMMEDIATE, \
  42. "/error", \
  43. "sis", \
  44. path, \
  45. errcode, \
  46. value)
  47. Client::Client()
  48. {
  49. nsm_addr = 0;
  50. nsm_client_id = 0;
  51. _session_manager_name = 0;
  52. nsm_is_active = false;
  53. _server = 0;
  54. _st = 0;
  55. }
  56. Client::~Client()
  57. {
  58. if(_st)
  59. stop();
  60. if(_st)
  61. lo_server_thread_free(_st);
  62. else
  63. lo_server_free(_server);
  64. }
  65. void
  66. Client::announce(const char *application_name,
  67. const char *capabilities,
  68. const char *process_name)
  69. {
  70. // MESSAGE( "Announcing to NSM" );
  71. lo_address to = lo_address_new_from_url(nsm_url);
  72. if(!to)
  73. // MESSAGE( "Bad address" );
  74. return;
  75. int pid = (int)getpid();
  76. lo_send_from(to,
  77. _server,
  78. LO_TT_IMMEDIATE,
  79. "/nsm/server/announce",
  80. "sssiii",
  81. application_name,
  82. capabilities,
  83. process_name,
  84. 1,
  85. /* api_major_version */
  86. 0,
  87. /* api_minor_version */
  88. pid);
  89. lo_address_free(to);
  90. }
  91. void
  92. Client::progress(float p)
  93. {
  94. if(nsm_is_active)
  95. lo_send_from(nsm_addr,
  96. _server,
  97. LO_TT_IMMEDIATE,
  98. "/nsm/client/progress",
  99. "f",
  100. p);
  101. }
  102. void
  103. Client::is_dirty(void)
  104. {
  105. if(nsm_is_active)
  106. lo_send_from(nsm_addr,
  107. _server,
  108. LO_TT_IMMEDIATE,
  109. "/nsm/client/is_dirty",
  110. "");
  111. }
  112. void
  113. Client::is_clean(void)
  114. {
  115. if(nsm_is_active)
  116. lo_send_from(nsm_addr,
  117. _server,
  118. LO_TT_IMMEDIATE,
  119. "/nsm/client/is_clean",
  120. "");
  121. }
  122. void
  123. Client::message(int priority, const char *msg)
  124. {
  125. if(nsm_is_active)
  126. lo_send_from(nsm_addr,
  127. _server,
  128. LO_TT_IMMEDIATE,
  129. "/nsm/client/message",
  130. "is",
  131. priority,
  132. msg);
  133. }
  134. void
  135. Client::broadcast(lo_message msg)
  136. {
  137. if(nsm_is_active)
  138. lo_send_message_from(nsm_addr,
  139. _server,
  140. "/nsm/server/broadcast",
  141. msg);
  142. }
  143. void
  144. Client::check(int timeout)
  145. {
  146. if(lo_server_wait(_server, timeout))
  147. while(lo_server_recv_noblock(_server, 0)) {}
  148. }
  149. void
  150. Client::start()
  151. {
  152. lo_server_thread_start(_st);
  153. }
  154. void
  155. Client::stop()
  156. {
  157. lo_server_thread_stop(_st);
  158. }
  159. int
  160. Client::init(const char *nsm_url)
  161. {
  162. this->nsm_url = nsm_url;
  163. lo_address addr = lo_address_new_from_url(nsm_url);
  164. int proto = lo_address_get_protocol(addr);
  165. lo_address_free(addr);
  166. _server = lo_server_new_with_proto(NULL, proto, NULL);
  167. if(!_server)
  168. return -1;
  169. lo_server_add_method(_server, "/error", "sis", &Client::osc_error, this);
  170. lo_server_add_method(_server,
  171. "/reply",
  172. "ssss",
  173. &Client::osc_announce_reply,
  174. this);
  175. lo_server_add_method(_server,
  176. "/nsm/client/open",
  177. "sss",
  178. &Client::osc_open,
  179. this);
  180. lo_server_add_method(_server,
  181. "/nsm/client/save",
  182. "",
  183. &Client::osc_save,
  184. this);
  185. lo_server_add_method(_server,
  186. "/nsm/client/session_is_loaded",
  187. "",
  188. &Client::osc_session_is_loaded,
  189. this);
  190. lo_server_add_method(_server, NULL, NULL, &Client::osc_broadcast, this);
  191. return 0;
  192. }
  193. int
  194. Client::init_thread(const char *nsm_url)
  195. {
  196. this->nsm_url = nsm_url;
  197. lo_address addr = lo_address_new_from_url(nsm_url);
  198. int proto = lo_address_get_protocol(addr);
  199. lo_address_free(addr);
  200. _st = lo_server_thread_new_with_proto(NULL, proto, NULL);
  201. _server = lo_server_thread_get_server(_st);
  202. if(!_server || !_st)
  203. return -1;
  204. lo_server_thread_add_method(_st,
  205. "/error",
  206. "sis",
  207. &Client::osc_error,
  208. this);
  209. lo_server_thread_add_method(_st,
  210. "/reply",
  211. "ssss",
  212. &Client::osc_announce_reply,
  213. this);
  214. lo_server_thread_add_method(_st,
  215. "/nsm/client/open",
  216. "sss",
  217. &Client::osc_open,
  218. this);
  219. lo_server_thread_add_method(_st,
  220. "/nsm/client/save",
  221. "",
  222. &Client::osc_save,
  223. this);
  224. lo_server_thread_add_method(_st,
  225. "/nsm/client/session_is_loaded",
  226. "",
  227. &Client::osc_session_is_loaded,
  228. this);
  229. lo_server_thread_add_method(_st,
  230. NULL,
  231. NULL,
  232. &Client::osc_broadcast,
  233. this);
  234. return 0;
  235. }
  236. /************************/
  237. /* OSC Message Handlers */
  238. /************************/
  239. int
  240. Client::osc_broadcast(const char *path,
  241. const char *types,
  242. lo_arg **argv,
  243. int argc,
  244. lo_message msg,
  245. void *user_data)
  246. {
  247. return ((NSM::Client *)user_data)->command_broadcast(path, msg);
  248. }
  249. int
  250. Client::osc_save(const char *path,
  251. const char *types,
  252. lo_arg **argv,
  253. int argc,
  254. lo_message msg,
  255. void *user_data)
  256. {
  257. char *out_msg = NULL;
  258. int r = ((NSM::Client *)user_data)->command_save(&out_msg);
  259. if(r)
  260. OSC_REPLY_ERR(r, (out_msg ? out_msg : ""));
  261. else
  262. OSC_REPLY("OK");
  263. if(out_msg)
  264. free(out_msg);
  265. return 0;
  266. }
  267. int
  268. Client::osc_open(const char *path,
  269. const char *types,
  270. lo_arg **argv,
  271. int argc,
  272. lo_message msg,
  273. void *user_data)
  274. {
  275. char *out_msg = NULL;
  276. NSM::Client *nsm = (NSM::Client *)user_data;
  277. nsm->nsm_client_id = strdup(&argv[2]->s);
  278. int r = ((NSM::Client *)user_data)->command_open(&argv[0]->s,
  279. &argv[1]->s,
  280. &argv[2]->s,
  281. &out_msg);
  282. if(r)
  283. OSC_REPLY_ERR(r, (out_msg ? out_msg : ""));
  284. else
  285. OSC_REPLY("OK");
  286. if(out_msg)
  287. free(out_msg);
  288. return 0;
  289. }
  290. int
  291. Client::osc_session_is_loaded(const char *path,
  292. const char *types,
  293. lo_arg **argv,
  294. int argc,
  295. lo_message msg,
  296. void *user_data)
  297. {
  298. NSM::Client *nsm = (NSM::Client *)user_data;
  299. nsm->command_session_is_loaded();
  300. return 0;
  301. }
  302. int
  303. Client::osc_error(const char *path,
  304. const char *types,
  305. lo_arg **argv,
  306. int argc,
  307. lo_message msg,
  308. void *user_data)
  309. {
  310. if(strcmp(&argv[0]->s, "/nsm/server/announce"))
  311. return -1;
  312. NSM::Client *nsm = (NSM::Client *)user_data;
  313. // WARNING( "Failed to register with NSM: %s", &argv[2]->s );
  314. nsm->nsm_is_active = false;
  315. nsm->command_active(nsm->nsm_is_active);
  316. return 0;
  317. }
  318. int
  319. Client::osc_announce_reply(const char *path,
  320. const char *types,
  321. lo_arg **argv,
  322. int argc,
  323. lo_message msg,
  324. void *user_data)
  325. {
  326. if(strcmp(&argv[0]->s, "/nsm/server/announce"))
  327. return -1;
  328. NSM::Client *nsm = (NSM::Client *)user_data;
  329. // MESSAGE( "Successfully registered. NSM says: %s", &argv[1]->s );
  330. nsm->nsm_is_active = true;
  331. nsm->_session_manager_name = strdup(&argv[2]->s);
  332. nsm->nsm_addr =
  333. lo_address_new_from_url(lo_address_get_url(lo_message_get_source(
  334. msg)));
  335. nsm->command_active(nsm->nsm_is_active);
  336. return 0;
  337. }
  338. };