From fe4faaca1b079c0bdd63a1a0bafd695462672bff Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Wed, 8 Feb 2012 15:39:03 -0800 Subject: [PATCH] Mixer: Allow clients to query for available OSC paths. --- mixer/src/Controller_Module.C | 6 +-- mixer/src/Mixer.C | 34 ++++++----------- nonlib/OSC/Endpoint.C | 72 ++++++++++++++++++++++++++++++++++- nonlib/OSC/Endpoint.H | 8 +++- 4 files changed, 91 insertions(+), 29 deletions(-) diff --git a/mixer/src/Controller_Module.C b/mixer/src/Controller_Module.C index 7b91d08..b4305f0 100644 --- a/mixer/src/Controller_Module.C +++ b/mixer/src/Controller_Module.C @@ -106,7 +106,8 @@ Controller_Module::generate_osc_path () char *path; - asprintf( &path, "/mixer/%s/%s/%s", chain()->name(), p->module()->label(), p->name() ); + // /mixer/strip/STRIPNAME/control/MODULENAME/CONTROLNAME + asprintf( &path, "/mixer/strip/%s/control/%s/%s", chain()->name(), p->module()->label(), p->name() ); // Hack to keep spaces out of OSC URL... Probably need to handle other special characters similarly. for ( int i = strlen( path ); i--; ) @@ -114,7 +115,6 @@ Controller_Module::generate_osc_path () if ( path[i] == ' ' ) path[i] = '_'; } - return path; } @@ -133,7 +133,7 @@ Controller_Module::change_osc_path ( char *path ) if ( path ) { - mixer->osc_endpoint->add_method( path, "f", &Controller_Module::osc_control_change, this ); + mixer->osc_endpoint->add_method( path, "f", &Controller_Module::osc_control_change, this, "value" ); _osc_path = path; diff --git a/mixer/src/Mixer.C b/mixer/src/Mixer.C index 6f69a02..ed17c05 100644 --- a/mixer/src/Mixer.C +++ b/mixer/src/Mixer.C @@ -65,12 +65,6 @@ extern char *user_config_dir; /* OSC Message Handlers */ /************************/ -OSC_HANDLER( generic ) -{ - OSC_DMSG(); - - return 0; -} OSC_HANDLER( quit ) { @@ -125,14 +119,9 @@ OSC_HANDLER( new ) return 0; } -OSC_HANDLER( root ) -{ - OSC_DMSG(); - - OSC_REPLY( "load\nsave\nquit\nnew\n"); - - return 0; -} +// OSC_HANDLER( root ) +// { +// } OSC_HANDLER( add_strip ) { @@ -395,15 +384,14 @@ Mixer::init_osc ( const char *osc_port ) // if ( 1 >= lo_send_from( src, ((Mixer*)user_data)->osc_endpoint, LO_TT_IMMEDIATE, "/finger-reply", "s", s ) ) - osc_endpoint->add_method( "/nsm/quit", "", OSC_NAME( quit ), this ); - osc_endpoint->add_method( "/nsm/load", "ss", OSC_NAME( load ), this ); - osc_endpoint->add_method( "/nsm/save", "", OSC_NAME( save ), this ); - osc_endpoint->add_method( "/nsm/new", "ss", OSC_NAME( new ), this ); - osc_endpoint->add_method( "/nsm/", "", OSC_NAME( root ), this ); - osc_endpoint->add_method( "/finger", "", OSC_NAME( finger ), this ); - osc_endpoint->add_method( "/mixer/add_strip", "", OSC_NAME( add_strip ), this ); -// osc_endpoint->add_method( NULL, "", osc_generic, this ); - + osc_endpoint->add_method( "/nsm/quit", "", OSC_NAME( quit ), this, "" ); + osc_endpoint->add_method( "/nsm/load", "ss", OSC_NAME( load ), this, "path,display_name" ); + osc_endpoint->add_method( "/nsm/save", "", OSC_NAME( save ), this, "" ); + osc_endpoint->add_method( "/nsm/new", "ss", OSC_NAME( new ), this, "path,display_name" ); +// osc_endpoint->add_method( "/nsm/", "", OSC_NAME( root ), this ); + osc_endpoint->add_method( "/finger", "", OSC_NAME( finger ), this, "" ); + osc_endpoint->add_method( "/mixer/add_strip", "", OSC_NAME( add_strip ), this, "" ); + // osc_endpoint->start(); /* poll so we can keep OSC handlers running in the GUI thread and avoid extra sync */ diff --git a/nonlib/OSC/Endpoint.C b/nonlib/OSC/Endpoint.C index 3408a8f..66726b5 100644 --- a/nonlib/OSC/Endpoint.C +++ b/nonlib/OSC/Endpoint.C @@ -21,6 +21,7 @@ #include "debug.h" #include #include +#include #include "Endpoint.H" @@ -48,6 +49,11 @@ namespace OSC char *url = lo_server_get_url(_server); printf("OSC: %s\n",url); free(url); + + + add_method( NULL, "", &Endpoint::osc_generic, this, "" ); + +// _path_names = new std::list(); } Endpoint::~Endpoint ( ) @@ -56,12 +62,63 @@ namespace OSC lo_server_free( _server ); } + + int + Endpoint::osc_generic ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) + { + OSC_DMSG(); + + if ( path[ strlen(path) - 1 ] != '/' ) + { + DMESSAGE( "Unknown OSC signal %s", path ); + return 0; + } + + char *paths = ((Endpoint*)user_data)->get_paths( path ); + + ((Endpoint*)user_data)->send( lo_message_get_source( msg ), "/reply", path, paths ); + + free(paths); + + return 0; + } + + // returns a malloc()'d string containing path names beginning with /prefix/, newline separated + char * + Endpoint::get_paths ( const char *prefix ) + { + char *r = (char*)malloc( 1024 ); + r[0] = 0; + + for ( std::list::iterator i = _path_names.begin(); i != _path_names.end(); ++i ) + { + if ( ! *i ) + continue; + + if (! strncmp( *i, prefix, strlen(prefix) ) ) + { + r = (char*)realloc( r, strlen( r ) + strlen( *i ) + 2 ); + + strcat( r, *i ); + strcat( r, "\n" ); + } + } + + return r; + } + void - Endpoint::add_method ( const char *path, const char *typespec, lo_method_handler handler, void *user_data ) + Endpoint::add_method ( const char *path, const char *typespec, lo_method_handler handler, void *user_data, const char *argument_description ) { DMESSAGE( "Added OSC method %s (%s)", path, typespec ); lo_server_add_method( _server, path, typespec, handler, user_data ); + + char *stored_path; + + asprintf( &stored_path, "%s (%s); %s", path, typespec, argument_description ); + + _path_names.push_back( stored_path ); } void @@ -70,6 +127,18 @@ namespace OSC DMESSAGE( "Deleted OSC method %s (%s)", path, typespec ); lo_server_del_method( _server, path, typespec ); + + for ( std::list::iterator i = _path_names.begin(); i != _path_names.end(); ++i ) + { + if ( ! *i ) + continue; + + if ( ! strncmp( path, *i, index( *i, ' ' ) - *i ) ) + { + free( *i ); + i = _path_names.erase( i ); + } + } } /* void * */ @@ -146,7 +215,6 @@ namespace OSC } } - int Endpoint::send ( lo_address to, const char *path, std::list< OSC_Value > values ) { diff --git a/nonlib/OSC/Endpoint.H b/nonlib/OSC/Endpoint.H index 43f5b9f..d86048e 100644 --- a/nonlib/OSC/Endpoint.H +++ b/nonlib/OSC/Endpoint.H @@ -109,18 +109,24 @@ namespace OSC { static void error_handler(int num, const char *msg, const char *path); + + static int osc_generic ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ); + // Thread _thread; // lo_server_thread _st; lo_server _server; + std::list _path_names; + public: Endpoint ( const char *port = 0 ); ~Endpoint ( ); - void add_method ( const char *path, const char *typespec, lo_method_handler handler, void *user_data ); + char *get_paths ( const char *prefix ); + void add_method ( const char *path, const char *typespec, lo_method_handler handler, void *user_data, const char *argument_description ); void del_method ( const char *path, const char *typespec ); void start ( void ); void stop ( void );