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.

522 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 immediately */
  255. void
  256. Endpoint::wait ( int timeout ) const
  257. {
  258. lo_server_recv_noblock( _server, timeout );
  259. }
  260. /** Process events forever */
  261. void
  262. Endpoint::run ( void ) const
  263. {
  264. for ( ;; )
  265. {
  266. lo_server_recv( _server );
  267. }
  268. }
  269. int
  270. Endpoint::send ( lo_address to, const char *path, std::list< OSC_Value > values )
  271. {
  272. lo_message m = lo_message_new();
  273. for ( std::list< OSC_Value >::const_iterator i = values.begin();
  274. i != values.end();
  275. ++i )
  276. {
  277. const OSC_Value *ov = &(*i);
  278. switch ( ov->type() )
  279. {
  280. case 'f':
  281. DMESSAGE( "Adding float %f", ((OSC_Float*)ov)->value() );
  282. lo_message_add_float( m, ((OSC_Float*)ov)->value() );
  283. break;
  284. case 'i':
  285. DMESSAGE( "Adding int %i", ((OSC_Int*)ov)->value() );
  286. lo_message_add_int32( m, ((OSC_Int*)ov)->value() );
  287. break;
  288. case 's':
  289. DMESSAGE( "Adding string %s", ((OSC_String*)ov)->value() );
  290. lo_message_add_string( m, ((OSC_String*)ov)->value() );
  291. break;
  292. default:
  293. FATAL( "Unknown format: %c", ov->type() );
  294. break;
  295. }
  296. }
  297. DMESSAGE( "Path: %s", path );
  298. lo_bundle b = lo_bundle_new( LO_TT_IMMEDIATE );
  299. lo_bundle_add_message(b, path, m );
  300. int r = lo_send_bundle_from( to, _server, b );
  301. // int r = lo_send_message_from( to, _server, path, m );
  302. // lo_message_free( m );
  303. return r;
  304. }
  305. int
  306. Endpoint::send ( lo_address to, const char *path )
  307. {
  308. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "" );
  309. }
  310. int
  311. Endpoint::send ( lo_address to, const char *path, int v )
  312. {
  313. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "i", v );
  314. }
  315. int
  316. Endpoint::send ( lo_address to, const char *path, float v )
  317. {
  318. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "f", v );
  319. }
  320. int
  321. Endpoint::send ( lo_address to, const char *path, double v )
  322. {
  323. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "d", v );
  324. }
  325. int
  326. Endpoint::send ( lo_address to, const char *path, const char * v )
  327. {
  328. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "s", v );
  329. }
  330. int
  331. Endpoint::send ( lo_address to, const char *path, const char * v1, float v2 )
  332. {
  333. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sf", v1, v2 );
  334. }
  335. int
  336. Endpoint::send ( lo_address to, const char *path, const char * v1, const char *v2 )
  337. {
  338. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ss", v1, v2 );
  339. }
  340. int
  341. Endpoint::send ( lo_address to, const char *path, const char * v1, const char *v2, const char *v3 )
  342. {
  343. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sss", v1, v2, v3 );
  344. }
  345. int
  346. Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3, int v4 )
  347. {
  348. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "siii", v1, v2, v3, v4 );
  349. }
  350. int
  351. Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, int v3, int v4, int v5 )
  352. {
  353. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssiii", v1, v2, v3, v4, v5 );
  354. }
  355. int
  356. Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, int v5, int v6 )
  357. {
  358. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssiii", v1, v2, v3, v4, v5, v6 );
  359. }
  360. int
  361. Endpoint::send ( lo_address to, const char *path, const char *v1, int v2 )
  362. {
  363. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "si", v1, v2 );
  364. }
  365. int
  366. Endpoint::send ( lo_address to, const char *path, int v1, const char *v2 )
  367. {
  368. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "is", v1, v2 );
  369. }
  370. int
  371. Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, const char *v3 )
  372. {
  373. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sis", v1, v2, v3 );
  374. }
  375. int
  376. Endpoint::send ( lo_address to, const char *path, int v1, const char *v2, const char *v3, const char *v4 )
  377. {
  378. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "isss", v1, v2, v3, v4 );
  379. }
  380. int
  381. Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, const char *v3, const char *v4, const char *v5 )
  382. {
  383. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sisss", v1, v2, v3, v4, v5 );
  384. }
  385. int
  386. Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, const char *v4, const char *v5 )
  387. {
  388. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssss", v1, v2, v3, v4, v5 );
  389. }
  390. int
  391. Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, const char *v4 )
  392. {
  393. return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssss", v1, v2, v3, v4 );
  394. }
  395. int
  396. Endpoint::send ( lo_address to, const char *path, lo_message msg )
  397. {
  398. return lo_send_message_from( to, _server, path, msg );
  399. }
  400. }