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.

297 lines
9.0KB

  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 "../debug.h"
  19. #include "Client.H"
  20. #include <string.h>
  21. #include <sys/types.h>
  22. #include <unistd.h>
  23. #include <stdlib.h>
  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, ((NSM::Client*)user_data)->_server, LO_TT_IMMEDIATE, "/reply", "ss", path, value )
  32. #define OSC_REPLY_ERR( errcode, value ) lo_send_from( ((NSM::Client*)user_data)->nsm_addr, ((NSM::Client*)user_data)->_server, LO_TT_IMMEDIATE, "/error", "sis", path, errcode, value )
  33. Client::Client ( )
  34. {
  35. nsm_addr = 0;
  36. nsm_client_id = 0;
  37. _session_manager_name = 0;
  38. nsm_is_active = false;
  39. _server = 0;
  40. _st = 0;
  41. }
  42. Client::~Client ( )
  43. {
  44. if ( _st )
  45. stop();
  46. if ( _st )
  47. lo_server_thread_free( _st );
  48. else
  49. lo_server_free ( _server );
  50. }
  51. void
  52. Client::announce ( const char *application_name, const char *capabilities, const char *process_name )
  53. {
  54. MESSAGE( "Announcing to NSM" );
  55. lo_address to = lo_address_new_from_url( nsm_url );
  56. if ( ! to )
  57. {
  58. MESSAGE( "Bad address" );
  59. return;
  60. }
  61. int pid = (int)getpid();
  62. lo_send_from( to, _server, LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii",
  63. application_name,
  64. capabilities,
  65. process_name,
  66. 0, /* api_major_version */
  67. 5, /* api_minor_version */
  68. pid );
  69. lo_address_free( to );
  70. }
  71. void
  72. Client::progress ( float p )
  73. {
  74. if ( nsm_is_active )
  75. {
  76. lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/progress", "f", p );
  77. }
  78. }
  79. void
  80. Client::is_dirty ( void )
  81. {
  82. if ( nsm_is_active )
  83. {
  84. lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/is_dirty", "" );
  85. }
  86. }
  87. void
  88. Client::is_clean ( void )
  89. {
  90. if ( nsm_is_active )
  91. {
  92. lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/is_clean", "" );
  93. }
  94. }
  95. void
  96. Client::message ( int priority, const char *msg )
  97. {
  98. if ( nsm_is_active )
  99. {
  100. lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/message", "is", priority, msg );
  101. }
  102. }
  103. void
  104. Client::broadcast ( lo_message msg )
  105. {
  106. if ( nsm_is_active )
  107. {
  108. lo_send_message_from( nsm_addr, _server, "/nsm/server/broadcast", msg );
  109. }
  110. }
  111. void
  112. Client::check ( int timeout )
  113. {
  114. if ( lo_server_wait( _server, timeout ) )
  115. while ( lo_server_recv_noblock( _server, 0 ) ) {}
  116. }
  117. void
  118. Client::start ( )
  119. {
  120. lo_server_thread_start( _st );
  121. }
  122. void
  123. Client::stop ( )
  124. {
  125. lo_server_thread_stop( _st );
  126. }
  127. int
  128. Client::init ( const char *nsm_url )
  129. {
  130. this->nsm_url = nsm_url;
  131. lo_address addr = lo_address_new_from_url( nsm_url );
  132. int proto = lo_address_get_protocol( addr );
  133. lo_address_free( addr );
  134. _server = lo_server_new_with_proto( NULL, proto, NULL );
  135. if ( ! _server )
  136. return -1;
  137. lo_server_add_method( _server, "/error", "sis", &Client::osc_error, this );
  138. lo_server_add_method( _server, "/reply", "ssss", &Client::osc_announce_reply, this );
  139. lo_server_add_method( _server, "/nsm/client/open", "sss", &Client::osc_open, this );
  140. lo_server_add_method( _server, "/nsm/client/save", "", &Client::osc_save, this );
  141. lo_server_add_method( _server, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this );
  142. lo_server_add_method( _server, NULL, NULL, &Client::osc_broadcast, this );
  143. return 0;
  144. }
  145. int
  146. Client::init_thread ( const char *nsm_url )
  147. {
  148. this->nsm_url = nsm_url;
  149. lo_address addr = lo_address_new_from_url( nsm_url );
  150. int proto = lo_address_get_protocol( addr );
  151. lo_address_free( addr );
  152. _st = lo_server_thread_new_with_proto( NULL, proto, NULL );
  153. _server = lo_server_thread_get_server( _st );
  154. if ( ! _server || ! _st )
  155. return -1;
  156. lo_server_thread_add_method( _st, "/error", "sis", &Client::osc_error, this );
  157. lo_server_thread_add_method( _st, "/reply", "ssss", &Client::osc_announce_reply, this );
  158. lo_server_thread_add_method( _st, "/nsm/client/open", "sss", &Client::osc_open, this );
  159. lo_server_thread_add_method( _st, "/nsm/client/save", "", &Client::osc_save, this );
  160. lo_server_thread_add_method( _st, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this );
  161. lo_server_thread_add_method( _st, NULL, NULL, &Client::osc_broadcast, this );
  162. return 0;
  163. }
  164. /************************/
  165. /* OSC Message Handlers */
  166. /************************/
  167. int
  168. Client::osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  169. {
  170. return ((NSM::Client*)user_data)->command_broadcast( path, msg );
  171. }
  172. int
  173. Client::osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  174. {
  175. char *out_msg = NULL;
  176. int r = ((NSM::Client*)user_data)->command_save(&out_msg);
  177. if ( r )
  178. OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") );
  179. else
  180. OSC_REPLY( "OK" );
  181. if ( out_msg )
  182. free( out_msg );
  183. return 0;
  184. }
  185. int
  186. Client::osc_open ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  187. {
  188. char *out_msg = NULL;
  189. NSM::Client *nsm = (NSM::Client*)user_data;
  190. nsm->nsm_client_id = strdup( &argv[2]->s );
  191. int r = ((NSM::Client*)user_data)->command_open( &argv[0]->s, &argv[1]->s, &argv[2]->s, &out_msg);
  192. if ( r )
  193. OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") );
  194. else
  195. OSC_REPLY( "OK" );
  196. if ( out_msg )
  197. free( out_msg );
  198. return 0;
  199. }
  200. int
  201. Client::osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  202. {
  203. NSM::Client *nsm = (NSM::Client*)user_data;
  204. nsm->command_session_is_loaded();
  205. return 0;
  206. }
  207. int
  208. Client::osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  209. {
  210. if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) )
  211. return -1;
  212. NSM::Client *nsm = (NSM::Client*)user_data;
  213. WARNING( "Failed to register with NSM: %s", &argv[2]->s );
  214. nsm->nsm_is_active = false;
  215. nsm->command_active( nsm->nsm_is_active );
  216. return 0;
  217. }
  218. int
  219. Client::osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  220. {
  221. if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) )
  222. return -1;
  223. NSM::Client *nsm = (NSM::Client*)user_data;
  224. MESSAGE( "Successfully registered. NSM says: %s", &argv[1]->s );
  225. nsm->nsm_is_active = true;
  226. nsm->_session_manager_name = strdup( &argv[2]->s );
  227. nsm->nsm_addr = lo_address_new_from_url( lo_address_get_url( lo_message_get_source( msg ) ));
  228. nsm->command_active( nsm->nsm_is_active );
  229. return 0;
  230. }
  231. };