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.

286 lines
8.6KB

  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 *nash_url, 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( nash_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 ( )
  129. {
  130. _server = lo_server_new( NULL, NULL );
  131. if ( ! _server )
  132. return -1;
  133. lo_server_add_method( _server, "/error", "sis", &Client::osc_error, this );
  134. lo_server_add_method( _server, "/reply", "ssss", &Client::osc_announce_reply, this );
  135. lo_server_add_method( _server, "/nsm/client/open", "sss", &Client::osc_open, this );
  136. lo_server_add_method( _server, "/nsm/client/save", "", &Client::osc_save, this );
  137. lo_server_add_method( _server, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this );
  138. lo_server_add_method( _server, NULL, NULL, &Client::osc_broadcast, this );
  139. return 0;
  140. }
  141. int
  142. Client::init_thread ( )
  143. {
  144. _st = lo_server_thread_new( NULL, NULL );
  145. _server = lo_server_thread_get_server( _st );
  146. if ( ! _server || ! _st )
  147. return -1;
  148. lo_server_thread_add_method( _st, "/error", "sis", &Client::osc_error, this );
  149. lo_server_thread_add_method( _st, "/reply", "ssss", &Client::osc_announce_reply, this );
  150. lo_server_thread_add_method( _st, "/nsm/client/open", "sss", &Client::osc_open, this );
  151. lo_server_thread_add_method( _st, "/nsm/client/save", "", &Client::osc_save, this );
  152. lo_server_thread_add_method( _st, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this );
  153. lo_server_thread_add_method( _st, NULL, NULL, &Client::osc_broadcast, this );
  154. return 0;
  155. }
  156. /************************/
  157. /* OSC Message Handlers */
  158. /************************/
  159. int
  160. Client::osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  161. {
  162. return ((NSM::Client*)user_data)->command_broadcast( path, msg );
  163. }
  164. int
  165. Client::osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  166. {
  167. char *out_msg = NULL;
  168. int r = ((NSM::Client*)user_data)->command_save(&out_msg);
  169. if ( r )
  170. OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") );
  171. else
  172. OSC_REPLY( "OK" );
  173. if ( out_msg )
  174. free( out_msg );
  175. return 0;
  176. }
  177. int
  178. Client::osc_open ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  179. {
  180. char *out_msg = NULL;
  181. NSM::Client *nsm = (NSM::Client*)user_data;
  182. nsm->nsm_client_id = strdup( &argv[2]->s );
  183. int r = ((NSM::Client*)user_data)->command_open( &argv[0]->s, &argv[1]->s, &argv[2]->s, &out_msg);
  184. if ( r )
  185. OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") );
  186. else
  187. OSC_REPLY( "OK" );
  188. if ( out_msg )
  189. free( out_msg );
  190. return 0;
  191. }
  192. int
  193. Client::osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  194. {
  195. NSM::Client *nsm = (NSM::Client*)user_data;
  196. nsm->command_session_is_loaded();
  197. return 0;
  198. }
  199. int
  200. Client::osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  201. {
  202. if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) )
  203. return -1;
  204. NSM::Client *nsm = (NSM::Client*)user_data;
  205. WARNING( "Failed to register with NSM: %s", &argv[2]->s );
  206. nsm->nsm_is_active = false;
  207. nsm->command_active( nsm->nsm_is_active );
  208. return 0;
  209. }
  210. int
  211. Client::osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  212. {
  213. if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) )
  214. return -1;
  215. NSM::Client *nsm = (NSM::Client*)user_data;
  216. MESSAGE( "Successfully registered. NSM says: %s", &argv[1]->s );
  217. nsm->nsm_is_active = true;
  218. nsm->_session_manager_name = strdup( &argv[2]->s );
  219. nsm->nsm_addr = lo_address_new_from_url( lo_address_get_url( lo_message_get_source( msg ) ));
  220. nsm->command_active( nsm->nsm_is_active );
  221. return 0;
  222. }
  223. };