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.

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