Assists music production by grouping standalone programs into sessions. Community version of "Non Session Manager".
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.

684 lines
23KB

  1. /*************************************************************************/
  2. /* Copyright (C) 2012 Jonathan Moore Liles */
  3. /* Copyright (C) 2020- Nils Hilbricht */
  4. /* */
  5. /* Permission to use, copy, modify, and/or distribute this software for */
  6. /* any purpose with or without fee is hereby granted, provided that the */
  7. /* above copyright notice and this permission notice appear in all */
  8. /* copies. */
  9. /* */
  10. /* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL */
  11. /* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */
  12. /* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE */
  13. /* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL */
  14. /* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR */
  15. /* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER */
  16. /* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR */
  17. /* PERFORMANCE OF THIS SOFTWARE. */
  18. /*************************************************************************/
  19. /*************************************************************************/
  20. /* A simple, callback based C API for NSM clients. */
  21. /* */
  22. /* Simplified Example: */
  23. /* */
  24. /* #include "nsm.h" */
  25. /* */
  26. /* static nsm_client_t *nsm = 0; */
  27. /* static int wait_nsm = 1; */
  28. /* */
  29. /* int */
  30. /* cb_nsm_open ( const char *name, */
  31. /* const char *display_name, */
  32. /* const char *client_id, */
  33. /* char **out_msg, */
  34. /* void *userdata ) */
  35. /* { */
  36. /* do_open_stuff(); */
  37. /* wait_nsm = 0; */
  38. /* return ERR_OK; */
  39. /* } */
  40. /* */
  41. /* int */
  42. /* cb_nsm_save ( char **out_msg, */
  43. /* void *userdata ) */
  44. /* { */
  45. /* do_save_stuff(); */
  46. /* return ERR_OK; */
  47. /* } */
  48. /* */
  49. /* void */
  50. /* cb_nsm_show ( void *userdata ) */
  51. /* { */
  52. /* do_show_ui(); */
  53. /* nsm_send_is_shown ( nsm ); */
  54. /* } */
  55. /* */
  56. /* void */
  57. /* cb_nsm_hide ( void *userdata ) */
  58. /* { */
  59. /* do_hide_ui(); */
  60. /* nsm_send_is_hidden ( nsm ); */
  61. /* } */
  62. /* */
  63. /* gboolean */
  64. /* poll_nsm() */
  65. /* { */
  66. /* if ( nsm ) */
  67. /* { */
  68. /* nsm_check_nowait( nsm ); */
  69. /* return true; */
  70. /* } */
  71. /* return false; */
  72. /* } */
  73. /* */
  74. /* int main( int argc, char **argv ) */
  75. /* { */
  76. /* const char *nsm_url = getenv( "NSM_URL" ); */
  77. /* */
  78. /* if ( nsm_url ) */
  79. /* { */
  80. /* nsm = nsm_new(); */
  81. /* */
  82. /* nsm_set_open_callback( nsm, cb_nsm_open, 0 ); */
  83. /* nsm_set_save_callback( nsm, cb_nsm_save, 0 ); */
  84. /* */
  85. /* if ( 0 == nsm_init( nsm, nsm_url ) ) */
  86. /* { */
  87. /* nsm_send_announce( nsm, "FOO", ":optional-gui:", argv[0] );*/
  88. /* */
  89. /* ********************************************************************** */
  90. /* This will block for at most 100 sec and */
  91. /* waiting for the NSM server open callback. */
  92. /* DISCLAIMER: YOU MAY NOT NEED TO DO THAT. */
  93. /* ********************************************************************** */
  94. /* */
  95. /* int timeout = 0; */
  96. /* while ( wait_nsm ) */
  97. /* { */
  98. /* nsm_check_wait( nsm, 500 ); */
  99. /* timeout += 1; */
  100. /* if ( timeout > 200 ) */
  101. /* exit ( 1 ); */
  102. /* } */
  103. /* */
  104. /* ********************************************************************** */
  105. /* This will check if the server support optional-gui */
  106. /* and connect the callbacks when support is found. */
  107. /* If you don't use the above blocking block */
  108. /* this could be done in cb_nsm_open() as well. */
  109. /* DISCLAIMER: YOU MAY NOT NEED TO DO THAT. */
  110. /* ********************************************************************** */
  111. /* */
  112. /* if ( strstr( nsm_get_session_manager_features ( nsm ), */
  113. /* ":optional-gui:" ) ) */
  114. /* { */
  115. /* nsm_set_show_callback( nsm, cb_nsm_show, 0 ); */
  116. /* nsm_set_hide_callback( nsm, cb_nsm_hide, 0 ); */
  117. /* } */
  118. /* */
  119. /* ********************************************************************** */
  120. /* */
  121. /* do_timeout_add( 200, poll_nsm, Null ); */
  122. /* } */
  123. /* else */
  124. /* { */
  125. /* nsm_free( nsm ); */
  126. /* nsm = 0; */
  127. /* } */
  128. /* } */
  129. /* } */
  130. /**************************************************************************/
  131. #ifndef _NSM_H
  132. #define _NSM_H
  133. #define NSM_API_VERSION_MAJOR 1
  134. #define NSM_API_VERSION_MINOR 0
  135. #include <lo/lo.h>
  136. #include <string.h>
  137. #include <sys/types.h>
  138. #include <unistd.h>
  139. #include <stdlib.h>
  140. #include <stdio.h>
  141. typedef void * nsm_client_t;
  142. typedef int (nsm_open_callback)( const char *name, const char *display_name, const char *client_id, char **out_msg, void *userdata );
  143. typedef int (nsm_save_callback)( char **out_msg, void *userdata );
  144. typedef void (nsm_show_gui_callback)( void *userdata );
  145. typedef void (nsm_hide_gui_callback)( void *userdata );
  146. typedef void (nsm_active_callback)( int b, void *userdata );
  147. typedef void (nsm_session_is_loaded_callback)( void *userdata );
  148. typedef int (nsm_broadcast_callback)( const char *, lo_message m, void *userdata );
  149. #define _NSM() ((struct _nsm_client_t*)nsm)
  150. #define NSM_EXPORT __attribute__((unused)) static
  151. /* private parts */
  152. struct _nsm_client_t
  153. {
  154. const char *nsm_url;
  155. lo_server _server;
  156. lo_server_thread _st;
  157. lo_address nsm_addr;
  158. int nsm_is_active;
  159. char *nsm_client_id;
  160. char *_session_manager_name;
  161. char *_session_manager_features;
  162. nsm_open_callback *open;
  163. void *open_userdata;
  164. nsm_save_callback *save;
  165. void *save_userdata;
  166. nsm_show_gui_callback *show;
  167. void *show_userdata;
  168. nsm_hide_gui_callback *hide;
  169. void *hide_userdata;
  170. nsm_active_callback *active;
  171. void *active_userdata;
  172. nsm_session_is_loaded_callback *session_is_loaded;
  173. void *session_is_loaded_userdata;
  174. nsm_broadcast_callback *broadcast;
  175. void *broadcast_userdata;
  176. };
  177. enum
  178. {
  179. ERR_OK = 0,
  180. ERR_GENERAL = -1,
  181. ERR_INCOMPATIBLE_API = -2,
  182. ERR_BLACKLISTED = -3,
  183. ERR_LAUNCH_FAILED = -4,
  184. ERR_NO_SUCH_FILE = -5,
  185. ERR_NO_SESSION_OPEN = -6,
  186. ERR_UNSAVED_CHANGES = -7,
  187. ERR_NOT_NOW = -8
  188. };
  189. NSM_EXPORT
  190. int
  191. nsm_is_active ( nsm_client_t *nsm )
  192. {
  193. return _NSM()->nsm_is_active;
  194. }
  195. NSM_EXPORT
  196. const char *
  197. nsm_get_session_manager_name ( nsm_client_t *nsm )
  198. {
  199. return _NSM()->_session_manager_name;
  200. }
  201. NSM_EXPORT
  202. const char *
  203. nsm_get_session_manager_features ( nsm_client_t *nsm )
  204. {
  205. return _NSM()->_session_manager_features;
  206. }
  207. NSM_EXPORT
  208. nsm_client_t *
  209. nsm_new ( void )
  210. {
  211. struct _nsm_client_t *nsm = (struct _nsm_client_t*)malloc( sizeof( struct _nsm_client_t ) );
  212. nsm->nsm_url = 0;
  213. nsm->nsm_is_active = 0;
  214. nsm->nsm_client_id = 0;
  215. nsm->_server = 0;
  216. nsm->_st = 0;
  217. nsm->nsm_addr = 0;
  218. nsm->_session_manager_name = 0;
  219. nsm->open = 0;
  220. nsm->save = 0;
  221. nsm->show = 0;
  222. nsm->hide = 0;
  223. nsm->active = 0;
  224. nsm->session_is_loaded = 0;
  225. nsm->broadcast = 0;
  226. return (nsm_client_t *)nsm;
  227. }
  228. /*******************************************/
  229. /* CLIENT TO SERVER INFORMATIONAL MESSAGES */
  230. /*******************************************/
  231. NSM_EXPORT
  232. void
  233. nsm_send_is_dirty ( nsm_client_t *nsm )
  234. {
  235. if ( _NSM()->nsm_is_active )
  236. lo_send_from( _NSM()->nsm_addr, _NSM()->_server, LO_TT_IMMEDIATE, "/nsm/client/is_dirty", "" );
  237. }
  238. NSM_EXPORT
  239. void
  240. nsm_send_is_clean ( nsm_client_t *nsm )
  241. {
  242. if ( _NSM()->nsm_is_active )
  243. lo_send_from( _NSM()->nsm_addr, _NSM()->_server, LO_TT_IMMEDIATE, "/nsm/client/is_clean", "" );
  244. }
  245. NSM_EXPORT
  246. void
  247. nsm_send_is_shown ( nsm_client_t *nsm )
  248. {
  249. if ( _NSM()->nsm_is_active )
  250. lo_send_from( _NSM()->nsm_addr, _NSM()->_server, LO_TT_IMMEDIATE, "/nsm/client/gui_is_shown", "" );
  251. }
  252. NSM_EXPORT
  253. void
  254. nsm_send_is_hidden ( nsm_client_t *nsm )
  255. {
  256. if ( _NSM()->nsm_is_active )
  257. lo_send_from( _NSM()->nsm_addr, _NSM()->_server, LO_TT_IMMEDIATE, "/nsm/client/gui_is_hidden", "" );
  258. }
  259. NSM_EXPORT
  260. void
  261. nsm_send_progress ( nsm_client_t *nsm, float p )
  262. {
  263. if ( _NSM()->nsm_is_active )
  264. lo_send_from( _NSM()->nsm_addr, _NSM()->_server, LO_TT_IMMEDIATE, "/nsm/client/progress", "f", p );
  265. }
  266. NSM_EXPORT
  267. void
  268. nsm_send_message ( nsm_client_t *nsm, int priority, const char *msg )
  269. {
  270. if ( _NSM()->nsm_is_active )
  271. lo_send_from( _NSM()->nsm_addr, _NSM()->_server, LO_TT_IMMEDIATE, "/nsm/client/message", "is", priority, msg );
  272. }
  273. NSM_EXPORT void
  274. nsm_send_announce ( nsm_client_t *nsm, const char *app_name, const char *capabilities, const char *process_name )
  275. {
  276. lo_address to = lo_address_new_from_url( _NSM()->nsm_url );
  277. if ( ! to )
  278. {
  279. fprintf( stderr, "NSM: Bad address!" );
  280. return;
  281. }
  282. int pid = (int)getpid();
  283. lo_send_from( to, _NSM()->_server, LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii",
  284. app_name,
  285. capabilities,
  286. process_name,
  287. NSM_API_VERSION_MAJOR,
  288. NSM_API_VERSION_MINOR,
  289. pid );
  290. lo_address_free( to );
  291. }
  292. NSM_EXPORT void
  293. nsm_send_broadcast ( nsm_client_t *nsm, lo_message msg )
  294. {
  295. if ( _NSM()->nsm_is_active )
  296. lo_send_message_from( _NSM()->nsm_addr, _NSM()->_server, "/nsm/server/broadcast", msg );
  297. }
  298. NSM_EXPORT
  299. void
  300. nsm_check_wait ( nsm_client_t *nsm, int timeout )
  301. {
  302. if ( lo_server_wait( _NSM()->_server, timeout ) )
  303. while ( lo_server_recv_noblock( _NSM()->_server, 0 ) ) {}
  304. }
  305. NSM_EXPORT
  306. void
  307. nsm_check_nowait (nsm_client_t *nsm )
  308. {
  309. nsm_check_wait( nsm, 0 );
  310. }
  311. NSM_EXPORT
  312. void
  313. nsm_thread_start ( nsm_client_t *nsm )
  314. {
  315. lo_server_thread_start( _NSM()->_st );
  316. }
  317. NSM_EXPORT
  318. void
  319. nsm_thread_stop ( nsm_client_t *nsm )
  320. {
  321. lo_server_thread_stop( _NSM()->_st );
  322. }
  323. NSM_EXPORT void
  324. nsm_free ( nsm_client_t *nsm )
  325. {
  326. if ( _NSM()->_st )
  327. nsm_thread_stop( nsm );
  328. if ( _NSM()->_st )
  329. lo_server_thread_free( _NSM()->_st );
  330. else
  331. lo_server_free( _NSM()->_server );
  332. free( _NSM() );
  333. }
  334. /*****************/
  335. /* SET CALLBACKS */
  336. /*****************/
  337. NSM_EXPORT
  338. void
  339. nsm_set_open_callback( nsm_client_t *nsm, nsm_open_callback *open_callback, void *userdata )
  340. {
  341. _NSM()->open = open_callback;
  342. _NSM()->open_userdata = userdata;
  343. }
  344. NSM_EXPORT
  345. void
  346. nsm_set_save_callback( nsm_client_t *nsm, nsm_save_callback *save_callback, void *userdata )
  347. {
  348. _NSM()->save = save_callback;
  349. _NSM()->save_userdata = userdata;
  350. }
  351. NSM_EXPORT
  352. void
  353. nsm_set_show_callback( nsm_client_t *nsm, nsm_show_gui_callback *show_callback, void *userdata )
  354. {
  355. _NSM()->show = show_callback;
  356. _NSM()->show_userdata = userdata;
  357. }
  358. NSM_EXPORT
  359. void
  360. nsm_set_hide_callback( nsm_client_t *nsm, nsm_hide_gui_callback *hide_callback, void *userdata )
  361. {
  362. _NSM()->hide = hide_callback;
  363. _NSM()->hide_userdata = userdata;
  364. }
  365. NSM_EXPORT
  366. void
  367. nsm_set_active_callback( nsm_client_t *nsm, nsm_active_callback *active_callback, void *userdata )
  368. {
  369. _NSM()->active = active_callback;
  370. _NSM()->active_userdata = userdata;
  371. }
  372. NSM_EXPORT
  373. void
  374. nsm_set_session_is_loaded_callback( nsm_client_t *nsm, nsm_session_is_loaded_callback *session_is_loaded_callback, void *userdata )
  375. {
  376. _NSM()->session_is_loaded = session_is_loaded_callback;
  377. _NSM()->session_is_loaded_userdata = userdata;
  378. }
  379. NSM_EXPORT
  380. void
  381. nsm_set_broadcast_callback( nsm_client_t *nsm, nsm_broadcast_callback *broadcast_callback, void *userdata )
  382. {
  383. _NSM()->broadcast = broadcast_callback;
  384. _NSM()->broadcast_userdata = userdata;
  385. }
  386. /****************/
  387. /* OSC HANDLERS */
  388. /****************/
  389. #undef OSC_REPLY
  390. #undef OSC_REPLY_ERR
  391. #define OSC_REPLY( value ) lo_send_from( ((struct _nsm_client_t*)user_data)->nsm_addr, ((struct _nsm_client_t*)user_data)->_server, LO_TT_IMMEDIATE, "/reply", "ss", path, value )
  392. #define OSC_REPLY_ERR( errcode, value ) lo_send_from( ((struct _nsm_client_t*)user_data)->nsm_addr, ((struct _nsm_client_t*)user_data)->_server, LO_TT_IMMEDIATE, "/error", "sis", path, errcode, value )
  393. NSM_EXPORT int _nsm_osc_open ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  394. {
  395. (void) types;
  396. (void) argc;
  397. (void) msg;
  398. char *out_msg = NULL;
  399. struct _nsm_client_t *nsm = (struct _nsm_client_t*)user_data;
  400. nsm->nsm_client_id = strdup( &argv[2]->s );
  401. if ( ! nsm->open )
  402. return 0;
  403. int r = nsm->open( &argv[0]->s, &argv[1]->s, &argv[2]->s, &out_msg, nsm->open_userdata );
  404. if ( r )
  405. OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") );
  406. else
  407. OSC_REPLY( "OK" );
  408. if ( out_msg )
  409. free( out_msg );
  410. return 0;
  411. }
  412. NSM_EXPORT int _nsm_osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  413. {
  414. (void) types;
  415. (void) argv;
  416. (void) argc;
  417. (void) msg;
  418. char *out_msg = NULL;
  419. struct _nsm_client_t *nsm = (struct _nsm_client_t*)user_data;
  420. if ( ! nsm->save )
  421. return 0;
  422. int r = nsm->save(&out_msg, nsm->save_userdata );
  423. if ( r )
  424. OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") );
  425. else
  426. OSC_REPLY( "OK" );
  427. if ( out_msg )
  428. free( out_msg );
  429. return 0;
  430. }
  431. NSM_EXPORT int _nsm_osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  432. {
  433. (void) path;
  434. (void) types;
  435. (void) argc;
  436. if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) )
  437. return -1;
  438. struct _nsm_client_t *nsm = (struct _nsm_client_t*)user_data;
  439. fprintf( stderr, "NSM: Successfully registered. NSM says: %s", &argv[1]->s );
  440. nsm->nsm_is_active = 1;
  441. nsm->_session_manager_name = strdup( &argv[2]->s );
  442. nsm->_session_manager_features = strdup( &argv[3]->s );
  443. nsm->nsm_addr = lo_address_new_from_url( lo_address_get_url( lo_message_get_source( msg ) ));
  444. if ( nsm->active )
  445. nsm->active( nsm->nsm_is_active, nsm->active_userdata );
  446. return 0;
  447. }
  448. NSM_EXPORT int _nsm_osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  449. {
  450. (void) path;
  451. (void) types;
  452. (void) argc;
  453. (void) msg;
  454. if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) )
  455. return -1;
  456. struct _nsm_client_t *nsm = (struct _nsm_client_t*)user_data;
  457. fprintf( stderr, "NSM: Failed to register with NSM server: %s", &argv[2]->s );
  458. nsm->nsm_is_active = 0;
  459. if ( nsm->active )
  460. nsm->active( nsm->nsm_is_active, nsm->active_userdata );
  461. return 0;
  462. }
  463. NSM_EXPORT int _nsm_osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  464. {
  465. (void) path;
  466. (void) types;
  467. (void) argv;
  468. (void) argc;
  469. (void) msg;
  470. struct _nsm_client_t *nsm = (struct _nsm_client_t*)user_data;
  471. if ( ! nsm->session_is_loaded )
  472. return 0;
  473. nsm->session_is_loaded( nsm->session_is_loaded_userdata );
  474. return 0;
  475. }
  476. NSM_EXPORT int _nsm_osc_show ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  477. {
  478. struct _nsm_client_t *nsm = (struct _nsm_client_t*)user_data;
  479. if ( ! nsm->show )
  480. return 0;
  481. nsm->show( nsm->show_userdata );
  482. return 0;
  483. }
  484. NSM_EXPORT int _nsm_osc_hide ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  485. {
  486. struct _nsm_client_t *nsm = (struct _nsm_client_t*)user_data;
  487. if ( ! nsm->hide )
  488. return 0;
  489. nsm->hide( nsm->hide_userdata );
  490. return 0;
  491. }
  492. NSM_EXPORT int _nsm_osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  493. {
  494. (void) types;
  495. (void) argv;
  496. (void) argc;
  497. struct _nsm_client_t *nsm = (struct _nsm_client_t*)user_data;
  498. if ( ! nsm->broadcast )
  499. return 0;
  500. return nsm->broadcast( path, msg, nsm->broadcast_userdata );
  501. }
  502. NSM_EXPORT
  503. int
  504. nsm_init ( nsm_client_t *nsm, const char *nsm_url )
  505. {
  506. _NSM()->nsm_url = nsm_url;
  507. lo_address addr = lo_address_new_from_url( nsm_url );
  508. int proto = lo_address_get_protocol( addr );
  509. lo_address_free( addr );
  510. _NSM()->_server = lo_server_new_with_proto( NULL, proto, NULL );
  511. if ( ! _NSM()->_server )
  512. return -1;
  513. lo_server_add_method( _NSM()->_server, "/error", "sis", _nsm_osc_error, _NSM() );
  514. lo_server_add_method( _NSM()->_server, "/reply", "ssss", _nsm_osc_announce_reply, _NSM() );
  515. lo_server_add_method( _NSM()->_server, "/nsm/client/open", "sss", _nsm_osc_open, _NSM() );
  516. lo_server_add_method( _NSM()->_server, "/nsm/client/save", "", _nsm_osc_save, _NSM() );
  517. lo_server_add_method( _NSM()->_server, "/nsm/client/session_is_loaded", "", _nsm_osc_session_is_loaded, _NSM() );
  518. lo_server_add_method( _NSM()->_server, "/nsm/client/show_optional_gui", "", _nsm_osc_show, _NSM() );
  519. lo_server_add_method( _NSM()->_server, "/nsm/client/hide_optional_gui", "", _nsm_osc_hide, _NSM() );
  520. lo_server_add_method( _NSM()->_server, NULL, NULL, _nsm_osc_broadcast, _NSM() );
  521. return 0;
  522. }
  523. NSM_EXPORT
  524. int
  525. nsm_init_thread ( nsm_client_t *nsm, const char *nsm_url )
  526. {
  527. _NSM()->nsm_url = nsm_url;
  528. lo_address addr = lo_address_new_from_url( nsm_url );
  529. int proto = lo_address_get_protocol( addr );
  530. lo_address_free( addr );
  531. _NSM()->_st = lo_server_thread_new_with_proto( NULL, proto, NULL );
  532. _NSM()->_server = lo_server_thread_get_server( _NSM()->_st );
  533. if ( ! _NSM()->_server )
  534. return -1;
  535. lo_server_thread_add_method( _NSM()->_st, "/error", "sis", _nsm_osc_error, _NSM() );
  536. lo_server_thread_add_method( _NSM()->_st, "/reply", "ssss", _nsm_osc_announce_reply, _NSM() );
  537. lo_server_thread_add_method( _NSM()->_st, "/nsm/client/open", "sss", _nsm_osc_open, _NSM() );
  538. lo_server_thread_add_method( _NSM()->_st, "/nsm/client/save", "", _nsm_osc_save, _NSM() );
  539. lo_server_thread_add_method( _NSM()->_st, "/nsm/client/session_is_loaded", "", _nsm_osc_session_is_loaded, _NSM() );
  540. lo_server_thread_add_method( _NSM()->_st, "/nsm/client/show_optional_gui", "", _nsm_osc_show, _NSM() );
  541. lo_server_thread_add_method( _NSM()->_st, "/nsm/client/hide_optional_gui", "", _nsm_osc_hide, _NSM() );
  542. lo_server_thread_add_method( _NSM()->_st, NULL, NULL, _nsm_osc_broadcast, _NSM() );
  543. return 0;
  544. }
  545. #endif /* NSM_H */