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.

523 lines
15KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2010 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 <lo/lo.h>
  19. #include "debug.h"
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <assert.h>
  24. #include "Endpoint.H"
  25. #include "Thread.H"
  26. namespace OSC
  27. {
  28. void
  29. Endpoint::error_handler(int num, const char *msg, const char *path)
  30. {
  31. WARNING( "LibLO server error %d in path %s: %s\n", num, path, msg);
  32. }
  33. Endpoint::Endpoint ( )
  34. {
  35. }
  36. int
  37. Endpoint::init ( const char *port )
  38. {
  39. DMESSAGE( "Creating OSC server" );
  40. _server = lo_server_new( port, error_handler );
  41. if ( ! _server )
  42. {
  43. WARNING( "Error creating OSC server" );
  44. return -1;
  45. }
  46. // char *url = lo_server_get_url(_server);
  47. // printf("OSC: %s\n",url);
  48. // free(url);
  49. // add generic handler for path reporting.
  50. add_method( "/osc/query/parameters", "s", osc_query_parameters, this, "" );
  51. add_method( NULL, "", &Endpoint::osc_generic, this, "" );
  52. return 0;
  53. }
  54. Endpoint::~Endpoint ( )
  55. {
  56. // lo_server_thread_free( _st );
  57. lo_server_free( _server );
  58. }
  59. int
  60. Endpoint::osc_query_parameters ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  61. {
  62. OSC_DMSG();
  63. Endpoint *ep = (Endpoint*)user_data;
  64. const char *qpath = &argv[0]->s;
  65. Method_Data *md = NULL;
  66. for ( std::list<Method_Data *>::iterator i = ep->_methods.begin(); i != ep->_methods.end(); ++i )
  67. {
  68. if ( ! (*i)->path )
  69. continue;
  70. if ( ! strcmp( qpath, (*i)->path ) && (*i)->typespec )
  71. {
  72. md = *i;
  73. /* FIXME: what about the fact that there could be multiple messages with the same path but
  74. different typespecs ? */
  75. break;
  76. }
  77. }
  78. if ( ! md )
  79. {
  80. ep->send( lo_message_get_source( msg ), "/error", path,
  81. "Could not find specified path" );
  82. return 0;
  83. }
  84. char *r = (char*) malloc( 256 );
  85. r[0] = 0;
  86. for ( int i = 0; i < strlen( md->typespec ); ++i )
  87. {
  88. char desc[50];
  89. snprintf( desc, sizeof(desc), "f:%f:%f:%f\n",
  90. md->parameter_limits[i].min,
  91. md->parameter_limits[i].max,
  92. md->parameter_limits[i].default_value );
  93. r = (char*)realloc( r, strlen( r ) + strlen( desc ) + 2 );
  94. strcat( r, desc );
  95. strcat( r, "\n" );
  96. }
  97. ep->send( lo_message_get_source( msg ), "/reply", path,
  98. qpath,
  99. r );
  100. return 0;
  101. }
  102. int
  103. Endpoint::osc_generic ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
  104. {
  105. // OSC_DMSG();
  106. if ( path[ strlen(path) - 1 ] != '/' )
  107. return -1;
  108. char *paths = ((Endpoint*)user_data)->get_paths( path );
  109. ((Endpoint*)user_data)->send( lo_message_get_source( msg ), "/reply", path, paths );
  110. free(paths);
  111. return 0;
  112. }
  113. // returns a malloc()'d string containing path names beginning with /prefix/, newline separated
  114. char *
  115. Endpoint::get_paths ( const char *prefix )
  116. {
  117. char *r = (char*)malloc( 1024 );
  118. r[0] = 0;
  119. for ( std::list<Method_Data*>::const_iterator i = _methods.begin(); i != _methods.end(); ++i )
  120. {
  121. if ( ! (*i)->path )
  122. continue;
  123. if (! strncmp( (*i)->path, prefix, strlen(prefix) ) )
  124. {
  125. r = (char*)realloc( r, strlen( r ) + strlen( (*i)->path ) + 2 );
  126. /* asprintf( &stored_path, "%s (%s); %s", path, typespec, argument_description ); */
  127. strcat( r, (*i)->path );
  128. strcat( r, "\n" );
  129. }
  130. }
  131. return r;
  132. }
  133. void
  134. Endpoint::set_parameter_limits ( const char *path, const char *typespec,
  135. int index,
  136. float min, float max, float default_value )
  137. {
  138. assert( typespec );
  139. assert( index < strlen( typespec ) );
  140. for ( std::list<Method_Data *>::iterator i = _methods.begin(); i != _methods.end(); ++i )
  141. {
  142. if ( ! (*i)->path )
  143. continue;
  144. if ( ! strcmp( path, (*i)->path ) &&
  145. ! strcmp( typespec, (*i)->typespec ) )
  146. {
  147. (*i)->parameter_limits[index].min = min;
  148. (*i)->parameter_limits[index].max = max;
  149. (*i)->parameter_limits[index].default_value = default_value;
  150. break;
  151. }
  152. }
  153. }
  154. method_handle
  155. Endpoint::add_method ( const char *path, const char *typespec, lo_method_handler handler, void *user_data, const char *argument_description )
  156. {
  157. // DMESSAGE( "Added OSC method %s (%s)", path, typespec );
  158. lo_server_add_method( _server, path, typespec, handler, user_data );
  159. Method_Data *md = new Method_Data;
  160. if ( path )
  161. md->path = strdup( path );
  162. if ( typespec )
  163. md->typespec = strdup( typespec );
  164. if ( argument_description )
  165. md->documentation = strdup( argument_description );
  166. if ( typespec )
  167. md->parameter_limits = new Parameter_Limits[strlen(typespec)];
  168. _methods.push_back( md );
  169. return md;
  170. /* asprintf( &stored_path, "%s (%s); %s", path, typespec, argument_description ); */
  171. /* _path_names.push_back( stored_path ); */
  172. }
  173. void
  174. Endpoint::del_method ( const char *path, const char *typespec )
  175. {
  176. // DMESSAGE( "Deleted OSC method %s (%s)", path, typespec );
  177. lo_server_del_method( _server, path, typespec );
  178. for ( std::list<Method_Data *>::iterator i = _methods.begin(); i != _methods.end(); ++i )
  179. {
  180. if ( ! (*i)->path )
  181. continue;
  182. if ( ! strcmp( path, (*i)->path ) &&
  183. ! strcmp( typespec, (*i)->typespec ) )
  184. {
  185. delete *i;
  186. i = _methods.erase( i );
  187. break;
  188. }
  189. }
  190. }
  191. void
  192. Endpoint::del_method ( const method_handle mh )
  193. {
  194. // DMESSAGE( "Deleted OSC method %s (%s)", path, typespec );
  195. Method_Data *meth = const_cast<Method_Data*>( (const Method_Data*)mh );
  196. lo_server_del_method( _server, meth->path, meth->typespec );
  197. delete meth;
  198. _methods.remove( meth );
  199. /* for ( std::list<Method_Data *>::iterator i = _methods.begin(); i != _methods.end(); ++i ) */
  200. /* { */
  201. /* if ( ! (*i)->path ) */
  202. /* continue; */
  203. /* if ( ! strcmp( path, (*i)->path ) && */
  204. /* ! strcmp( typespec, (*i)->typespec ) ) */
  205. /* { */
  206. /* delete *i; */
  207. /* i = _methods.erase( i ); */
  208. /* break; */
  209. /* } */
  210. /* } */
  211. }
  212. void *
  213. Endpoint::osc_thread ( void * arg )
  214. {
  215. ((Endpoint*)arg)->osc_thread();
  216. return NULL;
  217. }
  218. void
  219. Endpoint::osc_thread ( void )
  220. {
  221. _thread.name( "OSC" );
  222. DMESSAGE( "OSC Thread running" );
  223. run();
  224. }
  225. void
  226. Endpoint::start ( void )
  227. {
  228. if ( !_thread.clone( &Endpoint::osc_thread, this ) )
  229. FATAL( "Could not create OSC thread" );
  230. /* lo_server_thread_start( _st ); */
  231. }
  232. void
  233. Endpoint::stop ( void )
  234. {
  235. _thread.join();
  236. // lo_server_thread_stop( _st );
  237. }
  238. int
  239. Endpoint::port ( void ) const
  240. {
  241. return lo_server_get_port( _server );
  242. }
  243. char *
  244. Endpoint::url ( void ) const
  245. {
  246. return lo_server_get_url( _server );
  247. }
  248. /** Process any waiting events and return immediately */
  249. void
  250. Endpoint::check ( void ) const
  251. {
  252. wait( 0 );
  253. }
  254. /** Process any waiting events and return after timeout */
  255. void
  256. Endpoint::wait ( int timeout ) const
  257. {
  258. if ( lo_server_wait( _server, timeout ) )
  259. while ( lo_server_recv_noblock( _server, 0 ) ) { }
  260. }
  261. /** Process events forever */
  262. void
  263. Endpoint::run ( void ) const
  264. {
  265. for ( ;; )
  266. {
  267. lo_server_recv( _server );
  268. }
  269. }
  270. int
  271. Endpoint::send ( lo_address to, const char *path, std::list< OSC_Value > values )
  272. {
  273. lo_message m = lo_message_new();
  274. for ( std::list< OSC_Value >::const_iterator i = values.begin();
  275. i != values.end();
  276. ++i )
  277. {
  278. const OSC_Value *ov = &(*i);
  279. switch ( ov->type() )
  280. {
  281. case 'f':
  282. // DMESSAGE( "Adding float %f", ((OSC_Float*)ov)->value() );
  283. lo_message_add_float( m, ((OSC_Float*)ov)->value() );
  284. break;
  285. case 'i':
  286. // DMESSAGE( "Adding int %i", ((OSC_Int*)ov)->value() );
  287. lo_message_add_int32( m, ((OSC_Int*)ov)->value() );
  288. break;
  289. case 's':
  290. // DMESSAGE( "Adding string %s", ((OSC_String*)ov)->value() );
  291. lo_message_add_string( m, ((OSC_String*)ov)->value() );
  292. break;
  293. default:
  294. FATAL( "Unknown format: %c", ov->type() );
  295. break;
  296. }
  297. }
  298. // DMESSAGE( "Path: %s", path );
  299. lo_bundle b = lo_bundle_new( LO_TT_IMMEDIATE );
  300. lo_bundle_add_message(b, path, m );
  301. int r = lo_send_bundle_from( to, _server, b );
  302. // int r = lo_send_message_from( to, _server, path, m );
  303. // lo_message_free( m );
  304. return r;
  305. }
  306. int
  307. Endpoint::send ( lo_address to, const char *path )
  308. {
  309. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "" );
  310. }
  311. int
  312. Endpoint::send ( lo_address to, const char *path, int v )
  313. {
  314. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "i", v );
  315. }
  316. int
  317. Endpoint::send ( lo_address to, const char *path, float v )
  318. {
  319. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "f", v );
  320. }
  321. int
  322. Endpoint::send ( lo_address to, const char *path, double v )
  323. {
  324. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "d", v );
  325. }
  326. int
  327. Endpoint::send ( lo_address to, const char *path, const char * v )
  328. {
  329. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "s", v );
  330. }
  331. int
  332. Endpoint::send ( lo_address to, const char *path, const char * v1, float v2 )
  333. {
  334. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sf", v1, v2 );
  335. }
  336. int
  337. Endpoint::send ( lo_address to, const char *path, const char * v1, const char *v2 )
  338. {
  339. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ss", v1, v2 );
  340. }
  341. int
  342. Endpoint::send ( lo_address to, const char *path, const char * v1, const char *v2, const char *v3 )
  343. {
  344. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sss", v1, v2, v3 );
  345. }
  346. int
  347. Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3, int v4 )
  348. {
  349. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "siii", v1, v2, v3, v4 );
  350. }
  351. int
  352. Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, int v3, int v4, int v5 )
  353. {
  354. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssiii", v1, v2, v3, v4, v5 );
  355. }
  356. int
  357. Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, int v5, int v6 )
  358. {
  359. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssiii", v1, v2, v3, v4, v5, v6 );
  360. }
  361. int
  362. Endpoint::send ( lo_address to, const char *path, const char *v1, int v2 )
  363. {
  364. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "si", v1, v2 );
  365. }
  366. int
  367. Endpoint::send ( lo_address to, const char *path, int v1, const char *v2 )
  368. {
  369. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "is", v1, v2 );
  370. }
  371. int
  372. Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, const char *v3 )
  373. {
  374. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sis", v1, v2, v3 );
  375. }
  376. int
  377. Endpoint::send ( lo_address to, const char *path, int v1, const char *v2, const char *v3, const char *v4 )
  378. {
  379. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "isss", v1, v2, v3, v4 );
  380. }
  381. int
  382. Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, const char *v3, const char *v4, const char *v5 )
  383. {
  384. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sisss", v1, v2, v3, v4, v5 );
  385. }
  386. int
  387. Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, const char *v4, const char *v5 )
  388. {
  389. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssss", v1, v2, v3, v4, v5 );
  390. }
  391. int
  392. Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, const char *v4 )
  393. {
  394. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssss", v1, v2, v3, v4 );
  395. }
  396. int
  397. Endpoint::send ( lo_address to, const char *path, lo_message msg )
  398. {
  399. return lo_send_message_from( to, _server, path, msg );
  400. }
  401. }