non/nonlib/OSC/Endpoint.C

1376 lines
36 KiB
C
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*******************************************************************************/
/* Copyright (C) 2010 Jonathan Moore Liles */
/* */
/* This program is free software; you can redistribute it and/or modify it */
/* under the terms of the GNU General Public License as published by the */
/* Free Software Foundation; either version 2 of the License, or (at your */
/* option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
/* more details. */
/* */
/* You should have received a copy of the GNU General Public License along */
/* with This program; see the file COPYING. If not,write to the Free Software */
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/
#include <lo/lo.h>
#include "debug.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "Endpoint.H"
#include "Thread.H"
#pragma GCC diagnostic ignored "-Wunused-parameter"
namespace OSC
{
/**********/
/* Method */
/**********/
Method::Method ( )
{
_path = _typespec = _documentation = 0;
}
Method::~Method ( )
{
if ( _path )
free( _path );
if ( _typespec )
free( _typespec );
}
/**********/
/* Signal */
/**********/
int Signal::next_id = 0;
Signal::Signal ( const char *path, Direction dir )
{
_direction = dir;
_path = strdup( path );
_id = ++next_id;
_value = 0.0f;
_endpoint = NULL;
_peer = NULL;
_documentation = 0;
_user_data = 0;
_connection_state_callback = 0;
_connection_state_userdata = 0;
}
Signal::~Signal ( )
{
if ( _endpoint )
{
_endpoint->del_signal( this );
}
free( _path );
_path = NULL;
_endpoint = NULL;
}
void
Signal::rename ( const char *path )
{
DMESSAGE( "Renaming signal %s to %s", this->path(), path );
free( _path );
_path = strdup( path );
_endpoint->send_signal_rename_notifications( this );
}
bool
Signal::is_connected_to ( const OSC::Signal *s ) const
{
for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
i != _outgoing.end();
++i )
{
if ( (*i)->_peer == s->_peer &&
(*i)->id() == s->id() )
return true;
}
return false;
}
void
Signal::value ( float f )
{
for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
i != _outgoing.end();
++i )
{
/* FIXME: won't work for loopback */
if ( (*i)->_value != f )
{
(*i)->_value = f;
_endpoint->send( (*i)->_peer->addr,
"/signal/change",
id(),
(*i)->id(),
f );
}
}
}
char *
Signal::get_output_connection_peer_name_and_path ( int n )
{
Signal *t = NULL;
int j = 0;
for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
i != _outgoing.end();
++i, ++j )
{
if ( j == n )
{
t = *i;
break;
}
}
// Signal *s = get_peer_signal_by_id( t->_peer, t->signal_id );
if ( t )
{
char *r;
asprintf( &r, "%s:%s", t->_peer->name, t->path() );
return r;
}
else
return NULL;
}
void
Endpoint::error_handler(int num, const char *msg, const char *path)
{
WARNING( "LibLO server error %d in path %s: %s\n", num, path, msg);
}
Endpoint::Endpoint ( )
{
_peer_scan_complete_callback = 0;
_peer_scan_complete_userdata = 0;
_server = 0;
_name = 0;
owner = 0;
}
int
Endpoint::init ( int proto, const char *port )
{
DMESSAGE( "Creating OSC server" );
_server = lo_server_new_with_proto( port, proto, error_handler );
if ( ! _server )
{
WARNING( "Error creating OSC server" );
return -1;
}
add_method( "/signal/hello", "ss", &Endpoint::osc_sig_hello, this, "" );
add_method( "/signal/connect", "ii", &Endpoint::osc_sig_connect, this, "" );
add_method( "/signal/disconnect", "ii", &Endpoint::osc_sig_disconnect, this, "" );
add_method( "/signal/renamed", "is", &Endpoint::osc_sig_renamed, this, "" );
add_method( "/signal/removed", "i", &Endpoint::osc_sig_removed, this, "" );
add_method( "/signal/created", "ssifff", &Endpoint::osc_sig_created, this, "" );
add_method( "/signal/change", "iif", &Endpoint::osc_sig_handler, this, "" );
add_method( "/signal/list", NULL, &Endpoint::osc_signal_lister, this, "" );
add_method( NULL, "", &Endpoint::osc_generic, this, "" );
add_method( "/reply", NULL, &Endpoint::osc_reply, this, "" );
return 0;
}
Endpoint::~Endpoint ( )
{
// lo_server_thread_free( _st );
if ( _server )
{
lo_server_free( _server );
_server = 0;
}
}
OSC::Signal *
Endpoint::find_target_by_peer_address ( std::list<Signal*> *l, lo_address addr )
{
for ( std::list<Signal*>::iterator i = l->begin();
i != l->end();
++i )
{
if ( address_matches( addr, (*i)->_peer->addr ) )
{
return *i;
}
}
return NULL;
}
OSC::Signal *
Endpoint::find_signal_by_id ( int id )
{
for ( std::list<Signal*>::iterator i = _signals.begin();
i != _signals.end();
++i )
{
if ( (*i)->id() == id )
return *i;
}
return NULL;
}
OSC::Signal *
Endpoint::find_peer_signal_by_path ( Peer *p, const char *path )
{
for ( std::list<Signal*>::iterator i = p->_signals.begin();
i != p->_signals.end();
++i )
{
if ( !strcmp( (*i)->path(), path ) )
return *i;
}
return NULL;
}
OSC::Signal *
Endpoint::find_peer_signal_by_id ( Peer *p, int id )
{
for ( std::list<Signal*>::iterator i = p->_signals.begin();
i != p->_signals.end();
++i )
{
if ( id == (*i)->id() )
return *i;
}
return NULL;
}
void
Endpoint::hello ( const char *url )
{
assert( name() );
lo_address addr = lo_address_new_from_url ( url );
char *our_url = this->url();
send( addr, "/signal/hello", name(), our_url );
free( our_url );
lo_address_free( addr );
}
int
Endpoint::osc_sig_hello ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
Endpoint *ep = (Endpoint*)user_data;
const char *peer_name = &argv[0]->s;
const char *peer_url = &argv[1]->s;
DMESSAGE( "Got hello from %s", peer_name );
if ( ! ep->find_peer_by_name( peer_name ) )
{
ep->scan_peer( peer_name, peer_url );
if ( ep->name() )
{
ep->hello( peer_url );
}
else
{
DMESSAGE( "Not sending hello because we don't have a name yet!" );
}
}
return 0;
}
int
Endpoint::osc_sig_disconnect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
int their_id = argv[0]->i;
int our_id = argv[1]->i;
Endpoint *ep = (Endpoint*)user_data;
Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
if ( ! p )
return 0;
Signal *ps = ep->find_peer_signal_by_id( p, their_id );
if ( ! ps )
return 0;
Signal *s = ep->find_signal_by_id( our_id );
if ( ! s )
return 0;
if ( s->_direction == Signal::Input )
{
s->_incoming.remove( ps );
DMESSAGE( "Peer %s has disconnected from signal %s", p->name, ps->path() );
if ( s->_connection_state_callback )
s->_connection_state_callback( s, s->_connection_state_userdata );
return 0;
}
return 0;
}
int
Endpoint::osc_sig_connect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
int their_id = argv[0]->i;
int our_id = argv[1]->i;
Endpoint *ep = (Endpoint*)user_data;
Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
if ( ! p )
{
WARNING( "Got connection signal from unknown peer" );
return 0;
}
Signal *ps = ep->find_peer_signal_by_id( p, their_id );
if ( ! ps )
{
WARNING( "Unknown source signal" );
return 0;
}
Signal *s = ep->find_signal_by_id( our_id );
if ( ! s )
{
WARNING( "Unknown destination signal" );
return 0;
}
DMESSAGE( "Peer %s has connected to signal %s", p->name, s->path() );
/* if ( s->_direction == Signal::Input ) */
/* { */
s->_incoming.push_back( ps );
/* make a record of it ourselves */
ps->_outgoing.push_back( s );
if ( s->_connection_state_callback )
s->_connection_state_callback( s, s->_connection_state_userdata );
/* return 0; */
/* } */
return 0;
}
int
Endpoint::osc_sig_removed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
int id = argv[0]->i;
Endpoint *ep = (Endpoint*)user_data;
Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
if ( ! p )
{
WARNING( "Got signal remove notification from unknown peer." );
return 0;
}
Signal *o = ep->find_peer_signal_by_id( p, id );
if ( ! o )
{
WARNING( "Unknown signal id %i", id );
return 0;
}
DMESSAGE( "Signal %s:%s was removed", o->_peer->name, o->path() );
/* disconnect it */
for ( std::list<Signal*>::iterator i = o->_outgoing.begin();
i != o->_outgoing.end();
++i )
{
ep->disconnect_signal( o, *i );
}
for ( std::list<Signal*>::iterator i = o->_incoming.begin();
i != o->_incoming.end();
++i )
{
ep->disconnect_signal( *i, o );
}
p->_signals.remove( o );
delete o;
return 0;
}
int
Endpoint::osc_sig_created ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
Endpoint *ep = (Endpoint*)user_data;
Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
if ( ! p )
{
WARNING( "Got signal creation from unknown peer." );
return 0;
}
const char *name = &argv[0]->s;
const char *direction = &argv[1]->s;
const int id = argv[2]->i;
const float min = argv[3]->f;
const float max = argv[4]->f;
const float default_value = argv[5]->f;
DMESSAGE( "Peer %s has created signal %s with id %i (%s %f %f %f)", p->name,
name, id, direction, min, max, default_value );
Signal::Direction dir = Signal::Input;
if ( !strcmp( direction, "in" ) )
dir = Signal::Input;
else if ( !strcmp( direction, "out" ) )
dir = Signal::Output;
Signal *s = new Signal( name, dir );
s->_peer = p;
s->_id = id;
s->parameter_limits( min, max, default_value );
p->_signals.push_back( s );
return 0;
}
int
Endpoint::osc_sig_renamed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
DMESSAGE( "Got renamed message." );
int id = argv[0]->i;
char *new_name = &argv[1]->s;
Endpoint *ep = (Endpoint*)user_data;
Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
if ( ! p )
{
WARNING( "Got signal rename notification from unknown peer." );
return 0;
}
Signal *o = ep->find_peer_signal_by_id( p, id );
if ( ! o )
{
WARNING( "Unknown signal id %i", id );
return 0;
}
DMESSAGE( "Signal %s:%s was renamed to %s", o->_peer->name, o->_path, path );
free( o->_path );
o->_path = strdup( new_name );
return 0;
}
int
Endpoint::osc_sig_handler ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
Signal *o;
float f = 0.0;
Endpoint *ep = NULL;
if ( !strcmp( path, "/signal/change" ) && !strcmp( types, "iif" ) )
{
/* accept a value for numbered signal */
int id = argv[1]->i;
f = argv[2]->f;
ep = (Endpoint*)user_data;
o = ep->find_signal_by_id( id );
if ( ! o )
{
WARNING( "Unknown signal id %i", id );
return 0;
}
}
else if ( ! strcmp( types, "f" ) )
{
/* accept a value for signal named in path */
o = (Signal*)user_data;
f = argv[0]->f;
}
else if ( ! types || 0 == types[0] )
{
/* reply with current value */
o = (Signal*)user_data;
o->_endpoint->send( lo_message_get_source( msg ), "/reply", path, o->value() );
return 0;
}
else
{
return -1;
}
Peer *p = NULL;
if ( ep )
p = ep->find_peer_by_address( lo_message_get_source( msg ) );
if ( !p )
{
DMESSAGE( "Signal change initiated by an unknown peer" );
/* message came from an unconnected peer, just set the value exactly */
}
else
{
/* message is from a connected source, do mixing. */
/* remote signal */
/* if ( t->_peer ) */
/* if ( 0 == o->_incoming.size() ) */
/* return 0; */
for ( std::list<Signal*>::const_iterator i = o->_incoming.begin();
i != o->_incoming.end();
++i )
{
if ( (*i)->id() == argv[0]->i )
{
(*i)->_value = f;
break;
}
}
f = 0.0;
for ( std::list<Signal*>::const_iterator i = o->_incoming.begin();
i != o->_incoming.end();
++i )
{
f += (*i)->_value;
}
}
o->_value = f;
o->_handler( f, o->_user_data );
return 0;
}
int
Endpoint::osc_generic ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
// OSC_DMSG();
if ( argc || path[ strlen(path) - 1 ] != '/' )
return -1;
Endpoint *ep = (Endpoint*)user_data;
for ( std::list<Method*>::const_iterator i = ep->_methods.begin(); i != ep->_methods.end(); ++i )
{
if ( ! (*i)->path() )
continue;
if (! strncmp( (*i)->path(), path, strlen(path) ) )
{
/* asprintf( &stored_path, "%s (%s); %s", path, typespec, argument_description ); */
((Endpoint*)user_data)->send( lo_message_get_source( msg ), "/reply", path, (*i)->path() );
}
}
((Endpoint*)user_data)->send( lo_message_get_source( msg ), "/reply", path );
return 0;
}
int
Endpoint::osc_signal_lister ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
// OSC_DMSG();
const char *prefix = NULL;
if ( argc )
prefix = &argv[0]->s;
Endpoint *ep = (Endpoint*)user_data;
for ( std::list<Signal*>::const_iterator i = ep->_signals.begin(); i != ep->_signals.end(); ++i )
{
Signal *o = *i;
if ( ! prefix || ! strncmp( o->path(), prefix, strlen(prefix) ) )
{
ep->send( lo_message_get_source( msg ),
"/reply",
path,
o->path(),
o->_direction == Signal::Input ? "in" : "out",
o->id(),
o->parameter_limits().min,
o->parameter_limits().max,
o->parameter_limits().default_value
);
}
}
ep->send( lo_message_get_source( msg ), "/reply", path );
return 0;
}
bool
Endpoint::address_matches ( lo_address addr1, lo_address addr2 )
{
char *purl = strdup( lo_address_get_port( addr1 ) );
char *url = strdup( lo_address_get_port( addr2 ) );
bool r = !strcmp( purl, url );
free( purl );
free( url );
return r;
}
void
Endpoint::list_peer_signals ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v )
{
for ( std::list<Peer*>::iterator i = _peers.begin();
i != _peers.end();
++i )
{
for ( std::list<Signal*>::iterator j = (*i)->_signals.begin();
j != (*i)->_signals.end();
++j )
{
// DMESSAGE( "Running callback" );
callback( (*i)->name, *j, v );
}
}
}
Peer *
Endpoint::find_peer_by_address ( lo_address addr )
{
char *url = strdup( lo_address_get_port( addr ) );
Peer *p = NULL;
for ( std::list<Peer*>::iterator i = _peers.begin();
i != _peers.end();
++i )
{
char *purl = strdup( lo_address_get_port( (*i)->addr ) );
if ( !strcmp( purl, url ) )
{
free( purl );
p = *i;
break;
}
free(purl);
}
free( url );
return p;
}
Peer *
Endpoint::find_peer_by_name ( const char *name )
{
for ( std::list<Peer*>::iterator i = _peers.begin();
i != _peers.end();
++i )
{
if ( !strcmp( name, (*i)->name ) )
{
return *i;
}
}
return NULL;
}
bool
Endpoint::disconnect_signal ( OSC::Signal *s, OSC::Signal *d )
{
if ( ! s->is_connected_to( d ) )
return false;
MESSAGE( "Disconnecting signal output \"%s\" to %s:%i", s->path(), d->_peer->name, d->_id );
send( d->_peer->addr, "/signal/disconnect",
s->_id, /* our signal id */
d->_id /* their signal id */ );
s->_outgoing.remove( d );
s->_incoming.remove( d );
return true;
}
bool
Endpoint::disconnect_signal ( OSC::Signal *s, const char *peer_name, const char *signal_path )
{
if ( s->_direction == Signal::Output )
{
Peer *p = find_peer_by_name( peer_name );
if ( ! p )
return false;
Signal *ps = find_peer_signal_by_path( p, signal_path );
if ( ! ps )
return false;
if ( ! s->is_connected_to( ps ) )
return false;
return disconnect_signal( s, ps );
}
return false;
}
bool
Endpoint::connect_signal( OSC::Signal *s, const char *peer_and_path )
{
char peer[512];
char path[1024];
/* FIXME: use %a */
if ( 2 == sscanf( peer_and_path, "%[^:]:%s", peer, path ) )
{
return connect_signal( s, peer, path );
}
else
return false;
}
bool
Endpoint::connect_signal ( OSC::Signal *s, OSC::Signal *d )
{
if ( s->is_connected_to( d ) )
{
return false;
}
MESSAGE( "Connecting signal output \"%s\" to %s:%s", s->path(), d->_peer->name, d->path() );
s->_outgoing.push_back( d );
/* make a record of it ourselves */
d->_incoming.push_back( s );
send( d->_peer->addr, "/signal/connect",
s->_id, /* our signal id */
d->_id /* their signal id */ );
return true;
}
bool
Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path )
{
if ( s->_direction == Signal::Output )
{
Peer *p = find_peer_by_name( peer_name );
if ( ! p )
return false;
Signal *ps = find_peer_signal_by_path( p, signal_path );
if ( ! ps )
return false;
return connect_signal( s, ps );
}
return false;
}
bool
Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, int signal_id )
{
if ( s->_direction == Signal::Output )
{
Peer *p = find_peer_by_name( peer_name );
if ( !p )
return false;
Signal *ps = find_peer_signal_by_id( p, signal_id );
if ( !ps )
return false;
return connect_signal( s, ps );
}
return false;
}
Signal *
Signal::get_peer_signal_by_id ( Peer *p, int signal_id )
{
for ( std::list<Signal *>::iterator i = p->_signals.begin();
i != p->_signals.end();
++i )
{
if ( (*i)->_id == signal_id )
return *i;
}
return NULL;
}
int
Endpoint::osc_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
{
Endpoint *ep = (Endpoint*)user_data;
if ( argc && !strcmp( &argv[0]->s, "/signal/list" ) )
{
Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
if ( ! p )
{
WARNING( "Got input list reply from unknown peer." );
return 0;
}
if ( argc == 1 )
{
p->_scanning = false;
DMESSAGE( "Done scanning %s", p->name );
if ( ep->_peer_scan_complete_callback )
ep->_peer_scan_complete_callback(ep->_peer_scan_complete_userdata);
}
else if ( argc == 7 && p->_scanning )
{
DMESSAGE( "Peer %s has signal %s (%s)", p->name, &argv[1]->s, &argv[2]->s );
int dir = 0;
if ( !strcmp( &argv[2]->s, "in" ) )
dir = Signal::Input;
else if ( !strcmp( &argv[2]->s, "out" ) )
dir = Signal::Output;
Signal *s = new Signal( &argv[1]->s, (Signal::Direction)dir );
s->_peer = p;
s->_id = argv[3]->i;
s->parameter_limits( argv[4]->f, argv[5]->f, argv[6]->f );
p->_signals.push_back( s );
}
return 0;
}
else
return -1;
}
Method *
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 );
Method *md = new Method;
if ( path )
md->_path = strdup( path );
if ( typespec )
md->_typespec = strdup( typespec );
if ( argument_description )
md->_documentation = strdup( argument_description );
_methods.push_back( md );
return md;
}
Signal *
Endpoint::add_signal ( const char *path, Signal::Direction dir, float min, float max, float default_value, signal_handler handler, void *user_data )
{
Signal *o = new Signal( path, dir );
if ( path )
o->_path = strdup( path );
o->_handler = handler;
o->_user_data = user_data;
o->_endpoint = this;
_signals.push_back( o );
if ( dir == Signal::Input )
{
lo_server_add_method( _server, path, NULL, osc_sig_handler, o );
}
o->parameter_limits( min, max, default_value );
/* tell our peers about it */
for ( std::list<Peer*>::iterator i = _peers.begin();
i != _peers.end();
++i )
{
send( (*i)->addr,
"/signal/created",
o->path(),
o->_direction == Signal::Input ? "in" : "out",
o->id(),
min,
max,
default_value
);
}
return o;
}
void
Endpoint::del_method ( const char *path, const char *typespec )
{
// DMESSAGE( "Deleted OSC method %s (%s)", path, typespec );
lo_server_del_method( _server, path, typespec );
for ( std::list<Method *>::iterator i = _methods.begin(); i != _methods.end(); ++i )
{
if ( ! (*i)->path() )
continue;
if ( ! strcmp( path, (*i)->path() ) &&
! strcmp( typespec, (*i)->typespec() ) )
{
delete *i;
i = _methods.erase( i );
break;
}
}
}
void
Endpoint::del_method ( Method *meth )
{
// DMESSAGE( "Deleted OSC method %s (%s)", path, typespec );
lo_server_del_method( _server, meth->path(), meth->typespec() );
delete meth;
_methods.remove( meth );
}
void
Endpoint::send_signal_rename_notifications ( Signal *s )
{
for ( std::list<Peer*>::const_iterator i = _peers.begin();
i != _peers.end();
++i )
{
send( (*i)->addr,
"/signal/renamed",
s->id(),
s->path() );
}
}
void
Endpoint::del_signal ( Signal *o )
{
// DMESSAGE( "Deleted OSC method %s (%s)", path, typespec );
lo_server_del_method( _server, o->path(), "f" );
/* tell our peers about it */
for ( std::list<Peer*>::iterator i = _peers.begin();
i != _peers.end();
++i )
{
send( (*i)->addr,
"/signal/removed",
o->id() );
}
/* FIXME: clear loopback connections first! */
// delete o;
_signals.remove( o );
}
void
Endpoint::scan_peer ( const char *name, const char *url )
{
Peer *p = new Peer;
DMESSAGE( "Scanning peer %s @ %s...", name, url );
p->name = strdup( name );
p->addr = lo_address_new_from_url( url );
p->_scanning = true;
_peers.push_back( p );
send( p->addr, "/signal/list" );
}
void *
Endpoint::osc_thread ( void * arg )
{
((Endpoint*)arg)->osc_thread();
return NULL;
}
void
Endpoint::osc_thread ( void )
{
_thread.name( "OSC" );
DMESSAGE( "OSC Thread running" );
run();
}
void
Endpoint::start ( void )
{
if ( !_thread.clone( &Endpoint::osc_thread, this ) )
FATAL( "Could not create OSC thread" );
/* lo_server_thread_start( _st ); */
}
void
Endpoint::stop ( void )
{
_thread.join();
// lo_server_thread_stop( _st );
}
int
Endpoint::port ( void ) const
{
return lo_server_get_port( _server );
}
char *
Endpoint::url ( void ) const
{
return lo_server_get_url( _server );
}
/** Process any waiting events and return immediately */
void
Endpoint::check ( void ) const
{
wait( 0 );
}
/** Process any waiting events and return after timeout */
void
Endpoint::wait ( int timeout ) const
{
if ( lo_server_wait( _server, timeout ) )
while ( lo_server_recv_noblock( _server, 0 ) ) { }
}
/** Process events forever */
void
Endpoint::run ( void ) const
{
for ( ;; )
{
lo_server_recv( _server );
}
}
int
Endpoint::send ( lo_address to, const char *path, std::list< OSC_Value > values )
{
lo_message m = lo_message_new();
for ( std::list< OSC_Value >::const_iterator i = values.begin();
i != values.end();
++i )
{
const OSC_Value *ov = &(*i);
switch ( ov->type() )
{
case 'f':
DMESSAGE( "Adding float %f", ((OSC_Float*)ov)->value() );
lo_message_add_float( m, ((OSC_Float*)ov)->value() );
break;
case 'i':
DMESSAGE( "Adding int %i", ((OSC_Int*)ov)->value() );
lo_message_add_int32( m, ((OSC_Int*)ov)->value() );
break;
case 's':
DMESSAGE( "Adding string %s", ((OSC_String*)ov)->value() );
lo_message_add_string( m, ((OSC_String*)ov)->value() );
break;
default:
FATAL( "Unknown format: %c", ov->type() );
break;
}
}
DMESSAGE( "Path: %s", path );
lo_bundle b = lo_bundle_new( LO_TT_IMMEDIATE );
lo_bundle_add_message(b, path, m );
int r = lo_send_bundle_from( to, _server, b );
// int r = lo_send_message_from( to, _server, path, m );
// lo_message_free( m );
return r;
}
int
Endpoint::send ( lo_address to, const char *path )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "" );
}
int
Endpoint::send ( lo_address to, const char *path, int v )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "i", v );
}
int
Endpoint::send ( lo_address to, const char *path, float v )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "f", v );
}
int
Endpoint::send ( lo_address to, const char *path, double v )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "d", v );
}
int
Endpoint::send ( lo_address to, const char *path, const char * v )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "s", v );
}
int
Endpoint::send ( lo_address to, const char *path, const char * v1, float v2 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sf", v1, v2 );
}
int
Endpoint::send ( lo_address to, const char *path, const char * v1, const char *v2 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ss", v1, v2 );
}
int
Endpoint::send ( lo_address to, const char *path, const char * v1, const char *v2, const char *v3 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sss", v1, v2, v3 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3, int v4 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "siii", v1, v2, v3, v4 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, int v3, int v4, int v5 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssiii", v1, v2, v3, v4, v5 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, int v5, int v6 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssiii", v1, v2, v3, v4, v5, v6 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, int v2 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "si", v1, v2 );
}
int
Endpoint::send ( lo_address to, const char *path, int v1, const char *v2 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "is", v1, v2 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, const char *v3 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sis", v1, v2, v3 );
}
int
Endpoint::send ( lo_address to, const char *path, int v1, const char *v2, const char *v3, const char *v4 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "isss", v1, v2, v3, v4 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, const char *v3, const char *v4, const char *v5 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sisss", v1, v2, v3, v4, v5 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, const char *v4, const char *v5 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssss", v1, v2, v3, v4, v5 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, const char *v4 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssss", v1, v2, v3, v4 );
}
int
Endpoint::send ( lo_address to, const char *path, lo_message msg )
{
return lo_send_message_from( to, _server, path, msg );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, int v3, float v4, float v5, float v6 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssifff", v1, v2, v3, v4, v5, v6 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, float v5, float v6, float v7 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssifff", v1, v2, v3, v4, v5, v6, v7 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sii", v1, v2, v3 );
}
int
Endpoint::send ( lo_address to, const char *path, int v1, int v2 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ii", v1, v2 );
}
int
Endpoint::send ( lo_address to, const char *path, int v1, float v2 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "if", v1, v2 );
}
int
Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3, float v4 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "siif", v1, v2, v3, v4 );
}
int
Endpoint::send ( lo_address to, const char *path, int v1, int v2, float v3 )
{
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "iif", v1, v2, v3 );
}
}