Big OSC signal cleanups
This commit is contained in:
parent
cbf5fefa7b
commit
dafc476222
|
@ -48,6 +48,8 @@
|
||||||
#include <lo/lo.h>
|
#include <lo/lo.h>
|
||||||
#include "FL/Fl_Blinker.H"
|
#include "FL/Fl_Blinker.H"
|
||||||
|
|
||||||
|
#include "OSC/Endpoint.H"
|
||||||
|
|
||||||
const double STATUS_UPDATE_FREQ = 0.2f;
|
const double STATUS_UPDATE_FREQ = 0.2f;
|
||||||
|
|
||||||
const double OSC_INTERVAL = 1.0 / 20.0; /* 20 hz */
|
const double OSC_INTERVAL = 1.0 / 20.0; /* 20 hz */
|
||||||
|
@ -679,6 +681,22 @@ Mixer::handle ( int m )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Mixer::discover_peers ( void )
|
||||||
|
{
|
||||||
|
if ( nsm->is_active() )
|
||||||
|
{
|
||||||
|
lo_message m = lo_message_new();
|
||||||
|
|
||||||
|
lo_message_add_string( m, "/non/finger" );
|
||||||
|
lo_message_add_string( m, osc_endpoint->url() );
|
||||||
|
|
||||||
|
nsm->broadcast( m );
|
||||||
|
|
||||||
|
lo_message_free( m );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/************/
|
/************/
|
||||||
/* Commands */
|
/* Commands */
|
||||||
/************/
|
/************/
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
class Fl_Blinker;
|
class Fl_Blinker;
|
||||||
class Fl_Flowpack;
|
class Fl_Flowpack;
|
||||||
class Fl_Menu_Bar;
|
class Fl_Menu_Bar;
|
||||||
|
namespace OSC { class Endpoint; }
|
||||||
#include "OSC/Endpoint.H"
|
#include <lo/lo.h>
|
||||||
|
|
||||||
class Mixer : public Fl_Group
|
class Mixer : public Fl_Group
|
||||||
{
|
{
|
||||||
|
@ -105,6 +105,8 @@ public:
|
||||||
|
|
||||||
void say_hello ( void );
|
void say_hello ( void );
|
||||||
|
|
||||||
|
void discover_peers ( void );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool command_save ( void );
|
bool command_save ( void );
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#include "FL/menu_popup.H"
|
#include "FL/menu_popup.H"
|
||||||
#include "Mixer.H"
|
#include "Mixer.H"
|
||||||
|
|
||||||
|
#include "OSC/Endpoint.H"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Module *Module::_copied_module_empty = 0;
|
Module *Module::_copied_module_empty = 0;
|
||||||
|
@ -226,7 +228,7 @@ Module::Port::generate_osc_path ()
|
||||||
|
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
|
||||||
// /mixer/STRIPNAME/MODULENAME/CONTROLNAME
|
// /strip/STRIPNAME/MODULENAME/CONTROLNAME
|
||||||
|
|
||||||
if ( ! module()->allows_external_control() )
|
if ( ! module()->allows_external_control() )
|
||||||
{
|
{
|
||||||
|
@ -237,9 +239,9 @@ Module::Port::generate_osc_path ()
|
||||||
int n = module()->chain()->get_module_instance_number( module() );
|
int n = module()->chain()->get_module_instance_number( module() );
|
||||||
|
|
||||||
if ( n > 0 )
|
if ( n > 0 )
|
||||||
asprintf( &path, "/mixer/%s/%s.%i/%s", module()->chain()->name(), p->module()->label(), n, p->name() );
|
asprintf( &path, "/strip/%s/%s.%i/%s", module()->chain()->name(), p->module()->label(), n, p->name() );
|
||||||
else
|
else
|
||||||
asprintf( &path, "/mixer/%s/%s/%s", module()->chain()->name(), p->module()->label(), p->name() );
|
asprintf( &path, "/strip/%s/%s/%s", module()->chain()->name(), p->module()->label(), p->name() );
|
||||||
|
|
||||||
// Hack to keep spaces out of OSC URL... Probably need to handle other special characters similarly.
|
// Hack to keep spaces out of OSC URL... Probably need to handle other special characters similarly.
|
||||||
for ( int i = strlen( path ); i--; )
|
for ( int i = strlen( path ); i--; )
|
||||||
|
@ -251,6 +253,12 @@ Module::Port::generate_osc_path ()
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Module::Port::handle_signal_connection_state_changed ( OSC::Signal *s )
|
||||||
|
{
|
||||||
|
module()->redraw();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Module::Port::change_osc_path ( char *path )
|
Module::Port::change_osc_path ( char *path )
|
||||||
{
|
{
|
||||||
|
@ -261,20 +269,26 @@ Module::Port::change_osc_path ( char *path )
|
||||||
|
|
||||||
asprintf( &unscaled_path, "%s/unscaled", path );
|
asprintf( &unscaled_path, "%s/unscaled", path );
|
||||||
|
|
||||||
if ( ! ( _scaled_signal && _unscaled_signal ) )
|
if ( NULL == _scaled_signal )
|
||||||
{
|
{
|
||||||
_scaled_signal =
|
_scaled_signal =
|
||||||
mixer->osc_endpoint->add_signal( scaled_path,
|
mixer->osc_endpoint->add_signal( scaled_path,
|
||||||
OSC::Signal::Input, &Module::Port::osc_control_change_cv, this );
|
OSC::Signal::Input, &Module::Port::osc_control_change_cv, this );
|
||||||
|
|
||||||
|
_scaled_signal->signal_connection_state_changed.connect( sigc::mem_fun( this, &Module::Port::handle_signal_connection_state_changed ) );
|
||||||
|
|
||||||
_unscaled_signal =
|
_unscaled_signal =
|
||||||
mixer->osc_endpoint->add_signal( unscaled_path,
|
mixer->osc_endpoint->add_signal( unscaled_path,
|
||||||
OSC::Signal::Input, &Module::Port::osc_control_change_exact, this );
|
OSC::Signal::Input, &Module::Port::osc_control_change_exact, this );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DMESSAGE( "Renaming OSC signals" );
|
||||||
|
|
||||||
_scaled_signal->rename( scaled_path );
|
_scaled_signal->rename( scaled_path );
|
||||||
_unscaled_signal->rename( unscaled_path );
|
_unscaled_signal->rename( unscaled_path );
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free( unscaled_path );
|
free( unscaled_path );
|
||||||
|
@ -516,7 +530,7 @@ Module::draw_box ( void )
|
||||||
{
|
{
|
||||||
fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + 4, 5, 5, is_being_controlled() ? FL_YELLOW : fl_inactive( FL_YELLOW ) );
|
fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + 4, 5, 5, is_being_controlled() ? FL_YELLOW : fl_inactive( FL_YELLOW ) );
|
||||||
|
|
||||||
fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + 8, 5, 5, is_being_controlled_osc() ? FL_GREEN : fl_inactive( FL_GREEN ) );
|
fl_draw_box( FL_ROUNDED_BOX, tx + 4, ty + th - 8, 5, 5, is_being_controlled_osc() ? FL_YELLOW : fl_inactive( FL_YELLOW ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( control_output.size() )
|
if ( control_output.size() )
|
||||||
|
|
|
@ -170,13 +170,12 @@ public:
|
||||||
|
|
||||||
void update_osc_port ( )
|
void update_osc_port ( )
|
||||||
{
|
{
|
||||||
if ( INPUT == _direction )
|
// if ( INPUT == _direction )
|
||||||
change_osc_path( generate_osc_path() );
|
change_osc_path( generate_osc_path() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_osc_port ( )
|
void destroy_osc_port ( )
|
||||||
{
|
{
|
||||||
|
|
||||||
delete _unscaled_signal;
|
delete _unscaled_signal;
|
||||||
delete _scaled_signal;
|
delete _scaled_signal;
|
||||||
|
|
||||||
|
@ -256,8 +255,11 @@ public:
|
||||||
nframes_t _nframes;
|
nframes_t _nframes;
|
||||||
Module *_module;
|
Module *_module;
|
||||||
|
|
||||||
|
|
||||||
OSC::Signal *_scaled_signal;
|
OSC::Signal *_scaled_signal;
|
||||||
OSC::Signal *_unscaled_signal;
|
OSC::Signal *_unscaled_signal;
|
||||||
|
|
||||||
|
void handle_signal_connection_state_changed ( OSC::Signal *s );
|
||||||
};
|
};
|
||||||
|
|
||||||
void bbox ( int &X, int &Y, int &W, int &H )
|
void bbox ( int &X, int &Y, int &W, int &H )
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "NSM.H"
|
#include "NSM.H"
|
||||||
#include "Project.H"
|
#include "Project.H"
|
||||||
|
|
||||||
|
#include "OSC/Endpoint.H"
|
||||||
|
|
||||||
extern char *instance_name;
|
extern char *instance_name;
|
||||||
extern Mixer *mixer;
|
extern Mixer *mixer;
|
||||||
|
|
||||||
|
@ -101,6 +103,8 @@ NSM_Client::command_open ( const char *name, const char *display_name, const cha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mixer->discover_peers();
|
||||||
|
|
||||||
Fl::unlock();
|
Fl::unlock();
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -70,30 +70,24 @@ namespace OSC
|
||||||
void
|
void
|
||||||
Signal::rename ( const char *path )
|
Signal::rename ( const char *path )
|
||||||
{
|
{
|
||||||
for ( std::list<Target*>::const_iterator i = _incoming.begin();
|
DMESSAGE( "Renaming signal %s to %s", this->path(), path );
|
||||||
i != _incoming.end();
|
|
||||||
++i )
|
|
||||||
{
|
|
||||||
_endpoint->send( (*i)->peer->addr,
|
|
||||||
"/signal/renamed",
|
|
||||||
(*i)->signal_id,
|
|
||||||
path );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
free( _path );
|
free( _path );
|
||||||
_path = strdup( path );
|
_path = strdup( path );
|
||||||
|
|
||||||
|
_endpoint->send_signal_rename_notifications( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Signal::is_connected_to ( const OSC::Signal *s ) const
|
Signal::is_connected_to ( const OSC::Signal *s ) const
|
||||||
{
|
{
|
||||||
for ( std::list<Target*>::const_iterator i = _outgoing.begin();
|
for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
|
||||||
i != _outgoing.end();
|
i != _outgoing.end();
|
||||||
++i )
|
++i )
|
||||||
{
|
{
|
||||||
if ( (*i)->peer == s->_peer &&
|
if ( (*i)->_peer == s->_peer &&
|
||||||
(*i)->signal_id == s->id() )
|
(*i)->id() == s->id() )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,31 +97,47 @@ namespace OSC
|
||||||
void
|
void
|
||||||
Signal::value ( float f )
|
Signal::value ( float f )
|
||||||
{
|
{
|
||||||
for ( std::list<Target*>::const_iterator i = _outgoing.begin();
|
for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
|
||||||
i != _outgoing.end();
|
i != _outgoing.end();
|
||||||
++i )
|
++i )
|
||||||
{
|
{
|
||||||
if ( (*i)->value != f )
|
/* FIXME: won't work for loopback */
|
||||||
|
if ( (*i)->_value != f )
|
||||||
{
|
{
|
||||||
(*i)->value = f;
|
(*i)->_value = f;
|
||||||
|
|
||||||
_endpoint->send( (*i)->peer->addr,
|
_endpoint->send( (*i)->_peer->addr,
|
||||||
"/signal/change",
|
"/signal/change",
|
||||||
(*i)->signal_id,
|
id(),
|
||||||
|
(*i)->id(),
|
||||||
f );
|
f );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
char *
|
||||||
Signal::get_connected_peer_name_and_path ( char **peer_name, char **path )
|
Signal::get_output_connection_peer_name_and_path ( int n )
|
||||||
{
|
{
|
||||||
Target *t = _outgoing.back();
|
Signal *t;
|
||||||
|
|
||||||
Signal *s = get_peer_signal_by_id( t->peer, t->signal_id );
|
int j = 0;
|
||||||
|
for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
|
||||||
|
i != _outgoing.end();
|
||||||
|
++i, ++j )
|
||||||
|
{
|
||||||
|
if ( j == n )
|
||||||
|
{
|
||||||
|
t = *i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*peer_name = strdup( t->peer->name );
|
// Signal *s = get_peer_signal_by_id( t->_peer, t->signal_id );
|
||||||
*path = strdup( s->path() );
|
|
||||||
|
char *r;
|
||||||
|
asprintf( &r, "%s:%s", t->_peer->name, t->path() );
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -154,13 +164,15 @@ namespace OSC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
add_method( "/signal/hello", "s", &Endpoint::osc_sig_hello, this, "" );
|
add_method( "/signal/hello", "ss", &Endpoint::osc_sig_hello, this, "" );
|
||||||
add_method( "/signal/connect", "ii", &Endpoint::osc_sig_connect, this, "" );
|
add_method( "/signal/connect", "ii", &Endpoint::osc_sig_connect, this, "" );
|
||||||
add_method( "/signal/disconnect", "ii", &Endpoint::osc_sig_disconnect, this, "" );
|
add_method( "/signal/disconnect", "ii", &Endpoint::osc_sig_disconnect, this, "" );
|
||||||
add_method( "/signal/renamed", "is", &Endpoint::osc_sig_renamed, this, "" );
|
add_method( "/signal/renamed", "is", &Endpoint::osc_sig_renamed, this, "" );
|
||||||
add_method( "/signal/change", "if", &Endpoint::osc_sig_handler, this, "" );
|
add_method( "/signal/removed", "i", &Endpoint::osc_sig_removed, this, "" );
|
||||||
add_method( NULL, "", &Endpoint::osc_generic, 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( "/signal/list", NULL, &Endpoint::osc_signal_lister, this, "" );
|
||||||
|
add_method( NULL, "", &Endpoint::osc_generic, this, "" );
|
||||||
add_method( "/reply", NULL, &Endpoint::osc_reply, this, "" );
|
add_method( "/reply", NULL, &Endpoint::osc_reply, this, "" );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -173,15 +185,15 @@ namespace OSC
|
||||||
lo_server_free( _server );
|
lo_server_free( _server );
|
||||||
}
|
}
|
||||||
|
|
||||||
OSC::Target *
|
OSC::Signal *
|
||||||
Endpoint::find_target_by_peer_address ( std::list<Target*> *l, lo_address addr )
|
Endpoint::find_target_by_peer_address ( std::list<Signal*> *l, lo_address addr )
|
||||||
{
|
{
|
||||||
|
|
||||||
for ( std::list<Target*>::iterator i = l->begin();
|
for ( std::list<Signal*>::iterator i = l->begin();
|
||||||
i != l->end();
|
i != l->end();
|
||||||
++i )
|
++i )
|
||||||
{
|
{
|
||||||
if ( address_matches( addr, (*i)->peer->addr ) )
|
if ( address_matches( addr, (*i)->_peer->addr ) )
|
||||||
{
|
{
|
||||||
return *i;
|
return *i;
|
||||||
}
|
}
|
||||||
|
@ -237,8 +249,10 @@ namespace OSC
|
||||||
{
|
{
|
||||||
lo_address addr = lo_address_new_from_url ( url );
|
lo_address addr = lo_address_new_from_url ( url );
|
||||||
|
|
||||||
send( addr, "/signal/hello", name() );
|
char *our_url = this->url();
|
||||||
|
send( addr, "/signal/hello", name(), our_url );
|
||||||
|
free( our_url );
|
||||||
|
|
||||||
lo_address_free( addr );
|
lo_address_free( addr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,18 +262,15 @@ namespace OSC
|
||||||
Endpoint *ep = (Endpoint*)user_data;
|
Endpoint *ep = (Endpoint*)user_data;
|
||||||
|
|
||||||
const char *peer_name = &argv[0]->s;
|
const char *peer_name = &argv[0]->s;
|
||||||
|
const char *peer_url = &argv[1]->s;
|
||||||
|
|
||||||
DMESSAGE( "Got hello from %s", peer_name );
|
DMESSAGE( "Got hello from %s", peer_name );
|
||||||
|
|
||||||
if ( ! ep->find_peer_by_name( peer_name ) )
|
if ( ! ep->find_peer_by_name( peer_name ) )
|
||||||
{
|
{
|
||||||
char *url = lo_address_get_url( lo_message_get_source( msg ));
|
ep->scan_peer( peer_name, peer_url );
|
||||||
|
|
||||||
ep->scan_peer( peer_name, url );
|
ep->hello( peer_url );
|
||||||
|
|
||||||
ep->send( lo_message_get_source( msg ), "/signal/hello", ep->name() );
|
|
||||||
|
|
||||||
free(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -290,21 +301,13 @@ namespace OSC
|
||||||
|
|
||||||
if ( s->_direction == Signal::Input )
|
if ( s->_direction == Signal::Input )
|
||||||
{
|
{
|
||||||
for ( std::list<Target*>::iterator i = s->_incoming.begin();
|
s->_incoming.remove( ps );
|
||||||
i != s->_incoming.end();
|
|
||||||
++i )
|
DMESSAGE( "Peer %s has disconnected from signal %s", p->name, ps->path() );
|
||||||
{
|
|
||||||
if ( (*i)->peer == p &&
|
|
||||||
(*i)->signal_id == ps->id() )
|
|
||||||
{
|
|
||||||
DMESSAGE( "Peer %s has disconnected from signal %s", p->name, ps->path() );
|
|
||||||
|
|
||||||
delete *i;
|
s->signal_connection_state_changed( s );
|
||||||
i = s->_incoming.erase( i );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -347,24 +350,109 @@ namespace OSC
|
||||||
|
|
||||||
DMESSAGE( "Peer %s has connected to signal %s", p->name, s->path() );
|
DMESSAGE( "Peer %s has connected to signal %s", p->name, s->path() );
|
||||||
|
|
||||||
if ( s->_direction == Signal::Input )
|
/* if ( s->_direction == Signal::Input ) */
|
||||||
|
/* { */
|
||||||
|
s->_incoming.push_back( ps );
|
||||||
|
|
||||||
|
/* make a record of it ourselves */
|
||||||
|
ps->_outgoing.push_back( s );
|
||||||
|
|
||||||
|
s->signal_connection_state_changed( s );
|
||||||
|
|
||||||
|
/* 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 )
|
||||||
{
|
{
|
||||||
Target *t = new Target;
|
WARNING( "Got signal remove notification from unknown peer." );
|
||||||
|
|
||||||
t->peer = p;
|
|
||||||
t->signal_id = ps->id();
|
|
||||||
|
|
||||||
s->_incoming.push_back( t );
|
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
|
||||||
|
if ( ! argc )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
|
||||||
|
|
||||||
|
if ( ! p )
|
||||||
|
{
|
||||||
|
WARNING( "Got signal creation from unknown peer." );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DMESSAGE( "Peer %s has created signal %s", p->name, &argv[0]->s );
|
||||||
|
|
||||||
|
int dir = 0;
|
||||||
|
|
||||||
|
if ( !strcmp( &argv[1]->s, "in" ) )
|
||||||
|
dir = Signal::Input;
|
||||||
|
else if ( !strcmp( &argv[1]->s, "out" ) )
|
||||||
|
dir = Signal::Output;
|
||||||
|
|
||||||
|
Signal *s = new Signal( &argv[0]->s, (Signal::Direction)dir );
|
||||||
|
|
||||||
|
s->_peer = p;
|
||||||
|
s->_id = argv[2]->i;
|
||||||
|
s->parameter_limits( argv[3]->f, argv[4]->f, argv[5]->f );
|
||||||
|
|
||||||
|
p->_signals.push_back( s );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Endpoint::osc_sig_renamed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
|
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;
|
int id = argv[0]->i;
|
||||||
char *new_name = &argv[1]->s;
|
char *new_name = &argv[1]->s;
|
||||||
|
|
||||||
|
@ -386,7 +474,7 @@ namespace OSC
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DMESSAGE( "Signal %s was renamed to %s" );
|
DMESSAGE( "Signal %s:%s was renamed to %s", o->_peer->name, o->_path, path );
|
||||||
|
|
||||||
free( o->_path );
|
free( o->_path );
|
||||||
o->_path = strdup( new_name );
|
o->_path = strdup( new_name );
|
||||||
|
@ -399,13 +487,18 @@ namespace OSC
|
||||||
{
|
{
|
||||||
Signal *o;
|
Signal *o;
|
||||||
float f = 0.0;
|
float f = 0.0;
|
||||||
|
Endpoint *ep = NULL;
|
||||||
if ( !strcmp( path, "/signal/change" ) && !strcmp( types, "if" ) )
|
|
||||||
|
|
||||||
|
if ( !strcmp( path, "/signal/change" ) && !strcmp( types, "iif" ) )
|
||||||
{
|
{
|
||||||
/* accept a value for numbered signal */
|
/* accept a value for numbered signal */
|
||||||
int id = argv[0]->i;
|
int id = argv[1]->i;
|
||||||
f = argv[1]->f;
|
f = argv[2]->f;
|
||||||
o = ((Endpoint*)user_data)->find_signal_by_id( id );
|
ep = (Endpoint*)user_data;
|
||||||
|
|
||||||
|
o = ep->find_signal_by_id( id );
|
||||||
|
|
||||||
if ( ! o )
|
if ( ! o )
|
||||||
{
|
{
|
||||||
WARNING( "Unknown signal id %i", id );
|
WARNING( "Unknown signal id %i", id );
|
||||||
|
@ -429,26 +522,44 @@ namespace OSC
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target *t = NULL;
|
Peer *p = NULL;
|
||||||
|
|
||||||
if ( 0 == o->_incoming.size() ||
|
if ( ep )
|
||||||
! ( t = find_target_by_peer_address( &o->_incoming, lo_message_get_source( msg ) ) ) )
|
p = ep->find_peer_by_address( lo_message_get_source( msg ) );
|
||||||
|
|
||||||
|
if ( 0 == o->_incoming.size() )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ( !p )
|
||||||
{
|
{
|
||||||
|
DMESSAGE( "Signal change initiated by an unknown peer" );
|
||||||
/* message came from an unconnected peer, just set the value exactly */
|
/* message came from an unconnected peer, just set the value exactly */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* message is from a connected source, do mixing. */
|
/* message is from a connected source, do mixing. */
|
||||||
|
|
||||||
t->value = f;
|
/* remote signal */
|
||||||
|
/* if ( t->_peer ) */
|
||||||
|
|
||||||
f = 0.0;
|
for ( std::list<Signal*>::const_iterator i = o->_incoming.begin();
|
||||||
|
|
||||||
for ( std::list<Target*>::const_iterator i = o->_incoming.begin();
|
|
||||||
i != o->_incoming.end();
|
i != o->_incoming.end();
|
||||||
++i )
|
++i )
|
||||||
{
|
{
|
||||||
f += (*i)->value;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +710,25 @@ namespace OSC
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Endpoint::disconnect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path )
|
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 )
|
if ( s->_direction == Signal::Output )
|
||||||
{
|
{
|
||||||
|
@ -613,33 +742,53 @@ namespace OSC
|
||||||
if ( ! ps )
|
if ( ! ps )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MESSAGE( "Disconnecting signal output \"%s\" to %s:%i", s->path(), peer_name, ps->_id );
|
if ( ! s->is_connected_to( ps ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
for ( std::list<Target*>::iterator i = s->_outgoing.begin();
|
return disconnect_signal( s, ps );
|
||||||
i != s->_outgoing.end();
|
|
||||||
++i )
|
|
||||||
{
|
|
||||||
if ( (*i)->peer == p &&
|
|
||||||
(*i)->signal_id == ps->id() )
|
|
||||||
{
|
|
||||||
send( p->addr, "/signal/disconnect",
|
|
||||||
s->_id, /* our signal id */
|
|
||||||
(*i)->signal_id /* their signal id */ );
|
|
||||||
|
|
||||||
delete *i;
|
|
||||||
i = s->_outgoing.erase( i );
|
|
||||||
|
|
||||||
DMESSAGE( "Number of outgoing connections: %i", s->_outgoing.size() );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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
|
bool
|
||||||
Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path )
|
Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path )
|
||||||
{
|
{
|
||||||
|
@ -655,25 +804,7 @@ namespace OSC
|
||||||
if ( ! ps )
|
if ( ! ps )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( s->is_connected_to( ps ) )
|
return connect_signal( s, ps );
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
MESSAGE( "Connecting signal output \"%s\" to %s:%i", s->path(), peer_name, ps->_id );
|
|
||||||
|
|
||||||
Target *t = new Target();
|
|
||||||
|
|
||||||
t->peer = p;
|
|
||||||
t->signal_id = ps->_id;
|
|
||||||
|
|
||||||
s->_outgoing.push_back( t );
|
|
||||||
|
|
||||||
send( p->addr, "/signal/connect",
|
|
||||||
s->_id, /* our signal id */
|
|
||||||
t->signal_id /* their signal id */ );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -688,24 +819,13 @@ namespace OSC
|
||||||
|
|
||||||
if ( !p )
|
if ( !p )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MESSAGE( "Connecting signal output \"%s\" to %s:%i", s->path(), peer_name, signal_id );
|
|
||||||
|
|
||||||
if ( p )
|
Signal *ps = find_peer_signal_by_id( p, signal_id );
|
||||||
{
|
|
||||||
Target *t = new Target();
|
if ( !ps )
|
||||||
|
return false;
|
||||||
t->peer = p;
|
|
||||||
t->signal_id = signal_id;
|
return connect_signal( s, ps );
|
||||||
|
|
||||||
s->_outgoing.push_back( t );
|
|
||||||
|
|
||||||
send( p->addr, "/signal/connect",
|
|
||||||
s->_id, /* our signal id */
|
|
||||||
t->signal_id /* their signal id */ );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -745,10 +865,12 @@ namespace OSC
|
||||||
{
|
{
|
||||||
p->_scanning = false;
|
p->_scanning = false;
|
||||||
DMESSAGE( "Done scanning %s", p->name );
|
DMESSAGE( "Done scanning %s", p->name );
|
||||||
|
|
||||||
|
ep->signal_peer_scan_complete();
|
||||||
}
|
}
|
||||||
else if ( p->_scanning )
|
else if ( argc == 7 && p->_scanning )
|
||||||
{
|
{
|
||||||
DMESSAGE( "Peer %s has signal %s", p->name, &argv[1]->s );
|
DMESSAGE( "Peer %s has signal %s (%s)", p->name, &argv[1]->s, &argv[2]->s );
|
||||||
|
|
||||||
int dir = 0;
|
int dir = 0;
|
||||||
|
|
||||||
|
@ -761,9 +883,7 @@ namespace OSC
|
||||||
|
|
||||||
s->_peer = p;
|
s->_peer = p;
|
||||||
s->_id = argv[3]->i;
|
s->_id = argv[3]->i;
|
||||||
s->parameter_limits().min = argv[4]->f;
|
s->parameter_limits( argv[4]->f, argv[5]->f, argv[6]->f );
|
||||||
s->parameter_limits().max = argv[5]->f;
|
|
||||||
s->parameter_limits().default_value = argv[6]->f;
|
|
||||||
|
|
||||||
p->_signals.push_back( s );
|
p->_signals.push_back( s );
|
||||||
}
|
}
|
||||||
|
@ -790,9 +910,6 @@ namespace OSC
|
||||||
if ( argument_description )
|
if ( argument_description )
|
||||||
md->_documentation = strdup( argument_description );
|
md->_documentation = strdup( argument_description );
|
||||||
|
|
||||||
if ( typespec )
|
|
||||||
md->_parameter_limits = new Parameter_Limits[strlen(typespec)];
|
|
||||||
|
|
||||||
_methods.push_back( md );
|
_methods.push_back( md );
|
||||||
|
|
||||||
return md;
|
return md;
|
||||||
|
@ -801,23 +918,39 @@ namespace OSC
|
||||||
Signal *
|
Signal *
|
||||||
Endpoint::add_signal ( const char *path, Signal::Direction dir, signal_handler handler, void *user_data )
|
Endpoint::add_signal ( const char *path, Signal::Direction dir, signal_handler handler, void *user_data )
|
||||||
{
|
{
|
||||||
Signal *md = new Signal( path, dir );
|
Signal *o = new Signal( path, dir );
|
||||||
|
|
||||||
if ( path )
|
if ( path )
|
||||||
md->_path = strdup( path );
|
o->_path = strdup( path );
|
||||||
|
|
||||||
md->_handler = handler;
|
o->_handler = handler;
|
||||||
md->_user_data = user_data;
|
o->_user_data = user_data;
|
||||||
md->_endpoint = this;
|
o->_endpoint = this;
|
||||||
|
|
||||||
_signals.push_back( md );
|
_signals.push_back( o );
|
||||||
|
|
||||||
if ( dir == Signal::Input )
|
if ( dir == Signal::Input )
|
||||||
{
|
{
|
||||||
lo_server_add_method( _server, path, NULL, osc_sig_handler, md );
|
lo_server_add_method( _server, path, NULL, osc_sig_handler, o );
|
||||||
}
|
}
|
||||||
|
|
||||||
return md;
|
/* 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(),
|
||||||
|
o->parameter_limits().min,
|
||||||
|
o->parameter_limits().max,
|
||||||
|
o->parameter_limits().default_value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -855,6 +988,21 @@ namespace OSC
|
||||||
_methods.remove( 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
|
void
|
||||||
Endpoint::del_signal ( Signal *o )
|
Endpoint::del_signal ( Signal *o )
|
||||||
{
|
{
|
||||||
|
@ -862,6 +1010,17 @@ namespace OSC
|
||||||
|
|
||||||
lo_server_del_method( _server, o->path(), "f" );
|
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;
|
// delete o;
|
||||||
|
|
||||||
_signals.remove( o );
|
_signals.remove( o );
|
||||||
|
@ -1127,7 +1286,7 @@ namespace OSC
|
||||||
int
|
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 )
|
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, 7 );
|
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssifff", v1, v2, v3, v4, v5, v6, v7 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1147,4 +1306,16 @@ namespace OSC
|
||||||
{
|
{
|
||||||
return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "if", v1, 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 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sigc++/sigc++.h>
|
||||||
|
|
||||||
namespace OSC
|
namespace OSC
|
||||||
{
|
{
|
||||||
class OSC_Value
|
class OSC_Value
|
||||||
|
@ -125,13 +127,6 @@ namespace OSC
|
||||||
std::list<Signal*> _signals;
|
std::list<Signal*> _signals;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Target
|
|
||||||
{
|
|
||||||
Peer *peer;
|
|
||||||
int signal_id;
|
|
||||||
float value;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int (*signal_handler) ( float value, void *user_data );
|
typedef int (*signal_handler) ( float value, void *user_data );
|
||||||
|
|
||||||
class Signal
|
class Signal
|
||||||
|
@ -159,24 +154,17 @@ namespace OSC
|
||||||
|
|
||||||
float _value;
|
float _value;
|
||||||
|
|
||||||
std::list<Target*> _outgoing;
|
std::list<Signal*> _outgoing;
|
||||||
|
std::list<Signal*> _incoming;
|
||||||
|
|
||||||
Direction _direction;
|
Direction _direction;
|
||||||
|
|
||||||
/* FIXME:
|
|
||||||
In order to support signal mixing, the receiver must track
|
|
||||||
each connected signal channel separately, and add the
|
|
||||||
values together before invoking the handler.
|
|
||||||
*/
|
|
||||||
std::list<Target*> _incoming;
|
|
||||||
|
|
||||||
signal_handler _handler;
|
signal_handler _handler;
|
||||||
void *_user_data;
|
void *_user_data;
|
||||||
|
Parameter_Limits _parameter_limits;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Parameter_Limits _parameter_limits;
|
|
||||||
|
|
||||||
Signal ( const char *path, Direction dir )
|
Signal ( const char *path, Direction dir )
|
||||||
{
|
{
|
||||||
_direction = dir;
|
_direction = dir;
|
||||||
|
@ -187,12 +175,17 @@ namespace OSC
|
||||||
_peer = NULL;
|
_peer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigc::signal <void,Signal*> signal_connection_state_changed;
|
||||||
|
|
||||||
~Signal ( );
|
~Signal ( );
|
||||||
|
|
||||||
static Signal *get_peer_signal_by_id ( Peer *p, int signal_id );
|
static Signal *get_peer_signal_by_id ( Peer *p, int signal_id );
|
||||||
|
int noutput_connections() { return _outgoing.size(); }
|
||||||
bool connected ( void ) { return _outgoing.size() + _incoming.size(); }
|
bool connected ( void ) { return _outgoing.size() + _incoming.size(); }
|
||||||
void get_connected_peer_name_and_path ( char **peer_name, char **path );
|
|
||||||
|
char * get_output_connection_peer_name_and_path ( int n );
|
||||||
|
|
||||||
|
|
||||||
int id ( void ) const { return _id; }
|
int id ( void ) const { return _id; }
|
||||||
|
|
||||||
Direction direction ( void ) { return _direction; }
|
Direction direction ( void ) { return _direction; }
|
||||||
|
@ -205,7 +198,7 @@ namespace OSC
|
||||||
_value = default_value;
|
_value = default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Parameter_Limits& parameter_limits ( void ) { return _parameter_limits; }
|
const Parameter_Limits& parameter_limits ( void ) const { return _parameter_limits; }
|
||||||
|
|
||||||
const char *path ( void ) const { return _path; }
|
const char *path ( void ) const { return _path; }
|
||||||
|
|
||||||
|
@ -226,7 +219,6 @@ namespace OSC
|
||||||
char *_path;
|
char *_path;
|
||||||
char *_typespec;
|
char *_typespec;
|
||||||
char *_documentation;
|
char *_documentation;
|
||||||
struct Parameter_Limits *_parameter_limits;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -251,6 +243,8 @@ namespace OSC
|
||||||
static int osc_generic ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
static int osc_generic ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
||||||
static int osc_sig_handler ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
static int osc_sig_handler ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
||||||
static int osc_sig_renamed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
static int osc_sig_renamed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
||||||
|
static int osc_sig_removed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
||||||
|
static int osc_sig_created ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
||||||
static int osc_sig_disconnect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
static int osc_sig_disconnect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
||||||
static int osc_sig_connect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
static int osc_sig_connect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
||||||
static int osc_sig_hello ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
static int osc_sig_hello ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data );
|
||||||
|
@ -277,10 +271,13 @@ namespace OSC
|
||||||
Peer *find_peer_by_address ( lo_address addr );
|
Peer *find_peer_by_address ( lo_address addr );
|
||||||
static bool address_matches ( lo_address addr1, lo_address addr2 );
|
static bool address_matches ( lo_address addr1, lo_address addr2 );
|
||||||
|
|
||||||
static Target *find_target_by_peer_address ( std::list<Target*> *l, lo_address addr );
|
static Signal *find_target_by_peer_address ( std::list<Signal*> *l, lo_address addr );
|
||||||
|
|
||||||
char *_name;
|
char *_name;
|
||||||
|
|
||||||
|
void del_signal ( Signal *signal );
|
||||||
|
void send_signal_rename_notifications( Signal *s );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void list_peers ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v );
|
void list_peers ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v );
|
||||||
|
@ -291,16 +288,20 @@ namespace OSC
|
||||||
~Endpoint ( );
|
~Endpoint ( );
|
||||||
|
|
||||||
|
|
||||||
bool disconnect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path );
|
|
||||||
bool connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path );
|
|
||||||
bool connect_signal( OSC::Signal *s, const char *peer_name, int signal_id );
|
bool disconnect_signal ( OSC::Signal *s, OSC::Signal *d );
|
||||||
|
bool disconnect_signal ( OSC::Signal *s, const char *peer_name, const char *signal_path );
|
||||||
|
bool connect_signal ( OSC::Signal *s, OSC::Signal *d );
|
||||||
|
bool connect_signal ( OSC::Signal *s, const char *peer_name, const char *signal_path );
|
||||||
|
bool connect_signal ( OSC::Signal *s, const char *peer_name, int signal_id );
|
||||||
|
bool connect_signal ( OSC::Signal *s, const char *peer_and_path );
|
||||||
|
|
||||||
|
|
||||||
Signal *add_signal ( const char *path, Signal::Direction dir, signal_handler handler, void *user_data );
|
Signal *add_signal ( const char *path, Signal::Direction dir, signal_handler handler, void *user_data );
|
||||||
Method *add_method ( const char *path, const char *typespec, lo_method_handler handler, void *user_data, const char *argument_description );
|
Method *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 del_method ( const char *path, const char *typespec );
|
||||||
void del_method ( Method* method );
|
void del_method ( Method* method );
|
||||||
void del_signal ( Signal *signal );
|
|
||||||
void start ( void );
|
void start ( void );
|
||||||
void stop ( void );
|
void stop ( void );
|
||||||
int port ( void ) const;
|
int port ( void ) const;
|
||||||
|
@ -325,6 +326,7 @@ namespace OSC
|
||||||
int send ( lo_address to, const char *path, long v );
|
int send ( lo_address to, const char *path, long v );
|
||||||
int send ( lo_address to, const char *path, int v1, int v2 );
|
int send ( lo_address to, const char *path, int v1, int v2 );
|
||||||
int send ( lo_address to, const char *path, int v1, float v2 );
|
int send ( lo_address to, const char *path, int v1, float v2 );
|
||||||
|
int send ( lo_address to, const char *path, int v1, int v2, float v3 );
|
||||||
int send ( lo_address to, const char *path, const char *v );
|
int send ( lo_address to, const char *path, const char *v );
|
||||||
int send ( lo_address to, const char *path, const char *v1, float v2 );
|
int send ( lo_address to, const char *path, const char *v1, float v2 );
|
||||||
int send ( lo_address to, const char *path, const char *v1, int v2, int v3 );
|
int send ( lo_address to, const char *path, const char *v1, int v2, int v3 );
|
||||||
|
@ -335,6 +337,7 @@ namespace OSC
|
||||||
|
|
||||||
int send ( lo_address to, const char *path, const char *v1, int v2 );
|
int send ( lo_address to, const char *path, const char *v1, int v2 );
|
||||||
int send ( lo_address to, const char *path, int v1, const char *v2 );
|
int send ( lo_address to, const char *path, int v1, const char *v2 );
|
||||||
|
int send ( lo_address to, const char *path, const char *v1, int v2, int v3, float v4 );
|
||||||
|
|
||||||
int send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, int v5, int v6 );
|
int send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, int v5, int v6 );
|
||||||
int send ( lo_address to, const char *path, const char *v1, int v2, const char *v3 );
|
int send ( lo_address to, const char *path, const char *v1, int v2, const char *v3 );
|
||||||
|
@ -351,6 +354,11 @@ namespace OSC
|
||||||
|
|
||||||
// can be used to point back to owning object.
|
// can be used to point back to owning object.
|
||||||
void *owner;
|
void *owner;
|
||||||
|
|
||||||
|
sigc::signal <void> signal_peer_scan_complete;
|
||||||
|
|
||||||
|
friend Signal::~Signal();
|
||||||
|
friend void Signal::rename ( const char *name );
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,6 +32,8 @@ using std::list;
|
||||||
|
|
||||||
#include "Transport.H"
|
#include "Transport.H"
|
||||||
|
|
||||||
|
#include "OSC/Endpoint.H"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Control_Sequence::draw_with_gradient = true;
|
bool Control_Sequence::draw_with_gradient = true;
|
||||||
|
@ -44,28 +46,15 @@ Control_Sequence::Control_Sequence ( Track *track ) : Sequence( 0 )
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
_osc_connected_peer = _osc_connected_path = 0;
|
|
||||||
|
|
||||||
_track = track;
|
_track = track;
|
||||||
|
|
||||||
_output = new JACK::Port( engine, JACK::Port::Output, track->name(), track->ncontrols(), "cv" );
|
|
||||||
|
|
||||||
if ( ! _output->activate() )
|
|
||||||
{
|
|
||||||
FATAL( "could not create JACK port" );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* { */
|
|
||||||
/* char *path; */
|
|
||||||
/* asprintf( &path, "/non/daw/%s/control/%i", track->name(), track->ncontrols() ); */
|
|
||||||
|
|
||||||
/* _osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, NULL, NULL ); */
|
|
||||||
|
|
||||||
/* free( path ); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
_osc_output = 0;
|
_osc_output = 0;
|
||||||
|
_output = 0;
|
||||||
|
|
||||||
|
_mode = CV;
|
||||||
|
|
||||||
|
mode( OSC );
|
||||||
|
|
||||||
if ( track )
|
if ( track )
|
||||||
track->add( this );
|
track->add( this );
|
||||||
|
|
||||||
|
@ -90,25 +79,30 @@ Control_Sequence::~Control_Sequence ( )
|
||||||
|
|
||||||
engine->unlock();
|
engine->unlock();
|
||||||
|
|
||||||
_output->shutdown();
|
if ( _output )
|
||||||
|
{
|
||||||
|
_output->shutdown();
|
||||||
|
|
||||||
delete _output;
|
delete _output;
|
||||||
|
|
||||||
_output = NULL;
|
|
||||||
|
|
||||||
delete _osc_output;
|
|
||||||
|
|
||||||
_osc_output = NULL;
|
|
||||||
|
|
||||||
if ( _osc_connected_peer )
|
|
||||||
free( _osc_connected_peer );
|
|
||||||
|
|
||||||
_osc_connected_peer = NULL;
|
_output = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if ( _osc_connected_path )
|
if ( _osc_output )
|
||||||
free( _osc_connected_path );
|
{
|
||||||
|
delete _osc_output;
|
||||||
|
|
||||||
|
_osc_output = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
_osc_connected_path = NULL;
|
for ( list<char*>::iterator i = _persistent_osc_connections.begin();
|
||||||
|
i != _persistent_osc_connections.end();
|
||||||
|
++i )
|
||||||
|
{
|
||||||
|
free( *i );
|
||||||
|
}
|
||||||
|
|
||||||
|
_persistent_osc_connections.clear();
|
||||||
|
|
||||||
Loggable::block_end();
|
Loggable::block_end();
|
||||||
}
|
}
|
||||||
|
@ -123,7 +117,6 @@ Control_Sequence::init ( void )
|
||||||
color( fl_darker( FL_YELLOW ) );
|
color( fl_darker( FL_YELLOW ) );
|
||||||
|
|
||||||
interpolation( Linear );
|
interpolation( Linear );
|
||||||
frequency( 10 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -139,21 +132,24 @@ void
|
||||||
Control_Sequence::get_unjournaled ( Log_Entry &e ) const
|
Control_Sequence::get_unjournaled ( Log_Entry &e ) const
|
||||||
{
|
{
|
||||||
e.add( ":interpolation", _interpolation );
|
e.add( ":interpolation", _interpolation );
|
||||||
if ( _osc_output->connected() )
|
|
||||||
|
if ( _osc_output && _osc_output->connected() )
|
||||||
{
|
{
|
||||||
char *path;
|
DMESSAGE( "OSC Output connections: %i", _osc_output->noutput_connections() );
|
||||||
char *peer;
|
|
||||||
|
for ( int i = 0; i < _osc_output->noutput_connections(); ++i )
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
s = _osc_output->get_output_connection_peer_name_and_path(i);
|
||||||
|
|
||||||
|
e.add( ":osc-output", s );
|
||||||
|
|
||||||
_osc_output->get_connected_peer_name_and_path( &peer, &path );
|
free( s );
|
||||||
|
}
|
||||||
e.add( ":osc-peer", peer );
|
|
||||||
|
|
||||||
e.add( ":osc-path", path );
|
|
||||||
|
|
||||||
free( path );
|
|
||||||
free( peer );
|
|
||||||
}
|
}
|
||||||
/* e.add( ":frequency", frequency() ); */
|
|
||||||
|
e.add( ":mode", mode() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -188,21 +184,67 @@ Control_Sequence::set ( Log_Entry &e )
|
||||||
}
|
}
|
||||||
else if ( ! strcmp( ":interpolation", s ) )
|
else if ( ! strcmp( ":interpolation", s ) )
|
||||||
{
|
{
|
||||||
interpolation( (curve_type_e)atoi( v ) );
|
interpolation( (Curve_Type)atoi( v ) );
|
||||||
}
|
}
|
||||||
/* else if ( ! strcmp( ":frequency", s ) ) */
|
else if ( ! strcmp( ":mode", s ) )
|
||||||
/* frequency( atoi( v ) ); */
|
mode( (Mode)atoi( v ) );
|
||||||
else if ( ! strcmp( ":osc-peer", s ) )
|
else if ( ! strcmp( ":osc-output", s ) )
|
||||||
{
|
{
|
||||||
_osc_connected_peer = strdup( v );
|
_persistent_osc_connections.push_back( strdup( v ) );
|
||||||
}
|
|
||||||
else if ( !strcmp( ":osc-path", s ) )
|
|
||||||
{
|
|
||||||
_osc_connected_path = strdup( v );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Control_Sequence::mode ( Mode m )
|
||||||
|
{
|
||||||
|
if ( CV != m && mode() == CV )
|
||||||
|
{
|
||||||
|
if ( _output )
|
||||||
|
{
|
||||||
|
_output->shutdown();
|
||||||
|
|
||||||
|
delete _output;
|
||||||
|
|
||||||
|
_output = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( OSC != m && mode() == OSC )
|
||||||
|
{
|
||||||
|
if ( _osc_output )
|
||||||
|
{
|
||||||
|
delete _osc_output;
|
||||||
|
|
||||||
|
_osc_output = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CV == m && mode() != CV )
|
||||||
|
{
|
||||||
|
_output = new JACK::Port( engine, JACK::Port::Output, track()->name(), track()->ncontrols(), "cv" );
|
||||||
|
|
||||||
|
if ( ! _output->activate() )
|
||||||
|
{
|
||||||
|
fl_alert( "Could not create JACK port for control output on %s", track()->name() );
|
||||||
|
delete _output;
|
||||||
|
_output = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( OSC == m && mode() != OSC )
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
asprintf( &path, "/track/%s/control/%i", track()->name(), track()->ncontrols() );
|
||||||
|
|
||||||
|
_osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, NULL, NULL );
|
||||||
|
|
||||||
|
free( path );
|
||||||
|
|
||||||
|
connect_osc();
|
||||||
|
}
|
||||||
|
|
||||||
|
_mode = m;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Control_Sequence::draw_curve ( bool flip, bool filled )
|
Control_Sequence::draw_curve ( bool flip, bool filled )
|
||||||
{
|
{
|
||||||
|
@ -284,31 +326,31 @@ Control_Sequence::draw ( void )
|
||||||
const Fl_Color selection_color = active ? this->selection_color() : fl_inactive( this->selection_color() );
|
const Fl_Color selection_color = active ? this->selection_color() : fl_inactive( this->selection_color() );
|
||||||
|
|
||||||
|
|
||||||
if ( draw_with_gradient )
|
if ( draw_with_gradient )
|
||||||
{
|
{
|
||||||
/* const Fl_Color c2 = fl_color_average( selection_color, FL_WHITE, 0.90f ); */
|
/* const Fl_Color c2 = fl_color_average( selection_color, FL_WHITE, 0.90f ); */
|
||||||
/* const Fl_Color c1 = fl_color_average( color, c2, 0.60f ); */
|
/* const Fl_Color c1 = fl_color_average( color, c2, 0.60f ); */
|
||||||
|
|
||||||
const Fl_Color c1 = fl_color_average( selection_color, FL_WHITE, 0.90f );
|
const Fl_Color c1 = fl_color_average( selection_color, FL_WHITE, 0.90f );
|
||||||
const Fl_Color c2 = fl_color_average( color, c1, 0.60f );
|
const Fl_Color c2 = fl_color_average( color, c1, 0.60f );
|
||||||
|
|
||||||
for ( int gy = 0; gy < bh; gy++ )
|
for ( int gy = 0; gy < bh; gy++ )
|
||||||
{
|
|
||||||
fl_color( fl_color_average( c1, c2, gy / (float)bh) );
|
|
||||||
fl_line( X, by + gy, X + W, by + gy );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( draw_with_grid )
|
|
||||||
{
|
{
|
||||||
fl_color( fl_darker( color ) );
|
fl_color( fl_color_average( c1, c2, gy / (float)bh) );
|
||||||
|
fl_line( X, by + gy, X + W, by + gy );
|
||||||
const int inc = bh / 10;
|
|
||||||
if ( inc )
|
|
||||||
for ( int gy = 0; gy < bh; gy += inc )
|
|
||||||
fl_line( X, by + gy, X + W, by + gy );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( draw_with_grid )
|
||||||
|
{
|
||||||
|
fl_color( fl_darker( color ) );
|
||||||
|
|
||||||
|
const int inc = bh / 10;
|
||||||
|
if ( inc )
|
||||||
|
for ( int gy = 0; gy < bh; gy += inc )
|
||||||
|
fl_line( X, by + gy, X + W, by + gy );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if ( interpolation() != None )
|
if ( interpolation() != None )
|
||||||
{
|
{
|
||||||
|
@ -379,21 +421,34 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m )
|
||||||
|
|
||||||
*index( peer_name, '/' ) = 0;
|
*index( peer_name, '/' ) = 0;
|
||||||
|
|
||||||
_osc_connected_peer = strdup( peer_name );
|
const char *path = ((OSC::Signal*)m->mvalue()->user_data())->path();
|
||||||
|
|
||||||
_osc_connected_path = strdup( ((OSC::Signal*)m->mvalue()->user_data())->path() );
|
char *peer_and_path;
|
||||||
|
asprintf( &peer_and_path, "%s:%s", peer_name, path );
|
||||||
|
|
||||||
if ( ! _osc_output->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) )
|
if ( ! _osc_output->is_connected_to( ((OSC::Signal*)m->mvalue()->user_data()) ) )
|
||||||
{
|
{
|
||||||
|
_persistent_osc_connections.push_back( peer_and_path );
|
||||||
|
|
||||||
connect_osc();
|
connect_osc();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timeline->osc->disconnect_signal( _osc_output, _osc_connected_peer, _osc_connected_path );
|
timeline->osc->disconnect_signal( _osc_output, peer_name, path );
|
||||||
|
|
||||||
free( _osc_connected_path );
|
for ( std::list<char*>::iterator i = _persistent_osc_connections.begin();
|
||||||
free( _osc_connected_peer );
|
i != _persistent_osc_connections.end();
|
||||||
_osc_connected_peer = _osc_connected_path = NULL;
|
++i )
|
||||||
|
{
|
||||||
|
if ( !strcmp( *i, peer_and_path ) )
|
||||||
|
{
|
||||||
|
free( *i );
|
||||||
|
i = _persistent_osc_connections.erase( i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free( peer_and_path );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -401,18 +456,10 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m )
|
||||||
interpolation( Linear );
|
interpolation( Linear );
|
||||||
else if ( ! strcmp( picked, "Interpolation/None" ) )
|
else if ( ! strcmp( picked, "Interpolation/None" ) )
|
||||||
interpolation( None );
|
interpolation( None );
|
||||||
/* else if ( ! strcmp( picked, "Frequency/1Hz" ) ) */
|
else if ( ! strcmp( picked, "Mode/Control Signal (OSC)" ))
|
||||||
/* frequency( 1 ); */
|
mode( OSC );
|
||||||
/* else if ( ! strcmp( picked, "Frequency/5Hz" ) ) */
|
else if ( ! strcmp( picked, "Mode/Control Voltage (JACK)" ) )
|
||||||
/* frequency( 5 ); */
|
mode( CV );
|
||||||
/* else if ( ! strcmp( picked, "Frequency/10Hz" ) ) */
|
|
||||||
/* frequency( 10 ); */
|
|
||||||
/* else if ( ! strcmp( picked, "Frequency/20Hz" ) ) */
|
|
||||||
/* frequency( 20 ); */
|
|
||||||
/* else if ( ! strcmp( picked, "Frequency/30Hz" ) ) */
|
|
||||||
/* frequency( 30 ); */
|
|
||||||
/* else if ( ! strcmp( picked, "Frequency/60Hz" ) ) */
|
|
||||||
/* frequency( 60 ); */
|
|
||||||
|
|
||||||
else if ( ! strcmp( picked, "/Rename" ) )
|
else if ( ! strcmp( picked, "/Rename" ) )
|
||||||
{
|
{
|
||||||
|
@ -431,31 +478,23 @@ Control_Sequence::menu_cb ( const Fl_Menu_ *m )
|
||||||
|
|
||||||
void
|
void
|
||||||
Control_Sequence::connect_osc ( void )
|
Control_Sequence::connect_osc ( void )
|
||||||
|
|
||||||
{
|
{
|
||||||
if ( ! _osc_output )
|
if ( _persistent_osc_connections.size() )
|
||||||
{
|
{
|
||||||
char *path;
|
for ( std::list<char*>::iterator i = _persistent_osc_connections.begin();
|
||||||
asprintf( &path, "/non/daw/%s/control/%i", track()->name(), track()->ncontrols() );
|
i != _persistent_osc_connections.end();
|
||||||
|
++i )
|
||||||
_osc_output = timeline->osc->add_signal( path, OSC::Signal::Output, NULL, NULL );
|
|
||||||
|
|
||||||
free( path );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( _osc_connected_peer && _osc_connected_path )
|
|
||||||
{
|
|
||||||
if ( ! timeline->osc->connect_signal( _osc_output, _osc_connected_peer, _osc_connected_path ) )
|
|
||||||
{
|
{
|
||||||
// MESSAGE( "Failed to connect output %s to %s:%s", _osc_output->path(), _osc_connected_peer, _osc_connected_path );
|
if ( ! timeline->osc->connect_signal( _osc_output, *i ) )
|
||||||
}
|
{
|
||||||
else
|
// MESSAGE( "Failed to connect output %s to ", _osc_output->path(), *i );
|
||||||
{
|
}
|
||||||
tooltip( _osc_connected_path );
|
else
|
||||||
|
{
|
||||||
|
MESSAGE( "Connected output %s to %s", _osc_output->path(), *i );
|
||||||
|
|
||||||
// _osc_connected_peer = _osc_connected_path =
|
// tooltip( _osc_connected_path );
|
||||||
|
}
|
||||||
MESSAGE( "Connected output %s to %s:%s", _osc_output->path(), _osc_connected_peer, _osc_connected_path );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,10 +531,15 @@ Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig )
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
|
/* only list CV signals for now */
|
||||||
|
if ( ! ( sig->parameter_limits().min == 0.0 &&
|
||||||
|
sig->parameter_limits().max == 1.0 ) )
|
||||||
|
return;
|
||||||
|
|
||||||
asprintf( &s, "%s/%s%s", peer_prefix, name, sig->path() );
|
asprintf( &s, "%s/%s%s", peer_prefix, name, sig->path() );
|
||||||
|
|
||||||
peer_menu->add( s, 0, NULL, (void*)( sig ),
|
peer_menu->add( s, 0, NULL, (void*)( sig ),
|
||||||
FL_MENU_TOGGLE |
|
FL_MENU_TOGGLE |
|
||||||
( _osc_output->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) );
|
( _osc_output->is_connected_to( sig ) ? FL_MENU_VALUE : 0 ) );
|
||||||
|
|
||||||
free( s );
|
free( s );
|
||||||
|
@ -506,10 +550,10 @@ Control_Sequence::peer_callback( const char *name, const OSC::Signal *sig )
|
||||||
void
|
void
|
||||||
Control_Sequence::add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix )
|
Control_Sequence::add_osc_peers_to_menu ( Fl_Menu_Button *m, const char *prefix )
|
||||||
{
|
{
|
||||||
peer_menu = m;
|
peer_menu = m;
|
||||||
peer_prefix = prefix;
|
peer_prefix = prefix;
|
||||||
|
|
||||||
timeline->osc->list_peers( &Control_Sequence::peer_callback, this );
|
timeline->osc->list_peers( &Control_Sequence::peer_callback, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -549,37 +593,25 @@ Control_Sequence::handle ( int m )
|
||||||
}
|
}
|
||||||
else if ( Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_SHIFT | FL_CTRL ) ) )
|
else if ( Fl::event_button3() && ! ( Fl::event_state() & ( FL_ALT | FL_SHIFT | FL_CTRL ) ) )
|
||||||
{
|
{
|
||||||
timeline->discover_peers();
|
|
||||||
|
|
||||||
timeline->osc->wait( 500 );
|
|
||||||
|
|
||||||
Fl_Menu_Button menu( 0, 0, 0, 0, "Control Sequence" );
|
Fl_Menu_Button menu( 0, 0, 0, 0, "Control Sequence" );
|
||||||
|
|
||||||
/* Fl_Menu_Button *con = new Fl_Menu_Button( 0, 0, 0, 0 ); */
|
|
||||||
|
|
||||||
// con->callback( &Control_Sequence::menu_cb, (void*)this );
|
|
||||||
|
|
||||||
menu.clear();
|
menu.clear();
|
||||||
|
|
||||||
add_osc_peers_to_menu( &menu, "Connect To" );
|
if ( mode() == OSC )
|
||||||
|
{
|
||||||
|
add_osc_peers_to_menu( &menu, "Connect To" );
|
||||||
|
}
|
||||||
|
|
||||||
/* menu.add( "Connect To", 0, 0, 0); */
|
|
||||||
/* menu.add( "Connect To", 0, 0, const_cast< Fl_Menu_Item *>( con->menu() ), FL_SUBMENU_POINTER ); */
|
|
||||||
menu.add( "Interpolation/None", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == None ? FL_MENU_VALUE : 0 ) );
|
menu.add( "Interpolation/None", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == None ? FL_MENU_VALUE : 0 ) );
|
||||||
menu.add( "Interpolation/Linear", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == Linear ? FL_MENU_VALUE : 0 ) );
|
menu.add( "Interpolation/Linear", 0, 0, 0, FL_MENU_RADIO | ( interpolation() == Linear ? FL_MENU_VALUE : 0 ) );
|
||||||
|
menu.add( "Mode/Control Voltage (JACK)", 0, 0, 0 ,FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) );
|
||||||
/* menu.add( "Frequency/1Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 1 ? FL_MENU_VALUE : 0 ) ); */
|
menu.add( "Mode/Control Signal (OSC)", 0, 0, 0 , FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) );
|
||||||
/* menu.add( "Frequency/5Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 5 ? FL_MENU_VALUE : 0 ) ); */
|
|
||||||
/* menu.add( "Frequency/10Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 10 ? FL_MENU_VALUE : 0 ) ); */
|
|
||||||
/* menu.add( "Frequency/20Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 20 ? FL_MENU_VALUE : 0 ) ); */
|
|
||||||
/* menu.add( "Frequency/30Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 30 ? FL_MENU_VALUE : 0 ) ); */
|
|
||||||
/* menu.add( "Frequency/60Hz", 0, 0, 0, FL_MENU_RADIO | ( frequency() == 60 ? FL_MENU_VALUE : 0 ) ); */
|
|
||||||
|
|
||||||
|
|
||||||
menu.add( "Rename", 0, 0, 0 );
|
menu.add( "Rename", 0, 0, 0 );
|
||||||
menu.add( "Remove", 0, 0, 0 );
|
menu.add( "Remove", 0, 0, 0 );
|
||||||
|
|
||||||
menu.callback( &Control_Sequence::menu_cb, (void*)this);
|
menu.callback( &Control_Sequence::menu_cb, (void*)this);
|
||||||
|
|
||||||
menu_popup( &menu, x(), y() );
|
menu_popup( &menu, x(), y() );
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,14 @@ class Control_Sequence : public Sequence
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum curve_type_e { None, Linear, Quadratic };
|
enum Curve_Type { None, Linear, Quadratic };
|
||||||
|
|
||||||
|
enum Mode {
|
||||||
|
CV,
|
||||||
|
OSC,
|
||||||
|
MIDI
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -44,8 +51,7 @@ private:
|
||||||
|
|
||||||
/* these are used to cache the saved osc connection until the
|
/* these are used to cache the saved osc connection until the
|
||||||
* session is loaded, at which time we will reconnect */
|
* session is loaded, at which time we will reconnect */
|
||||||
char *_osc_connected_peer;
|
std::list<char*> _persistent_osc_connections;
|
||||||
char *_osc_connected_path;
|
|
||||||
/* osc output port */
|
/* osc output port */
|
||||||
OSC::Signal *_osc_output;
|
OSC::Signal *_osc_output;
|
||||||
|
|
||||||
|
@ -55,9 +61,7 @@ private:
|
||||||
|
|
||||||
bool _highlighted;
|
bool _highlighted;
|
||||||
|
|
||||||
curve_type_e _interpolation;
|
Curve_Type _interpolation;
|
||||||
int _frequency;
|
|
||||||
float _interval;
|
|
||||||
|
|
||||||
void init ( void );
|
void init ( void );
|
||||||
|
|
||||||
|
@ -66,6 +70,7 @@ private:
|
||||||
static void menu_cb ( Fl_Widget *w, void *v );
|
static void menu_cb ( Fl_Widget *w, void *v );
|
||||||
void menu_cb ( const Fl_Menu_ *m );
|
void menu_cb ( const Fl_Menu_ *m );
|
||||||
|
|
||||||
|
Mode _mode;
|
||||||
|
|
||||||
float _rate;
|
float _rate;
|
||||||
|
|
||||||
|
@ -87,6 +92,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
static void process_osc ( void *v );
|
static void process_osc ( void *v );
|
||||||
void process_osc ( void );
|
void process_osc ( void );
|
||||||
|
|
||||||
|
@ -103,10 +109,11 @@ public:
|
||||||
|
|
||||||
Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; }
|
Fl_Cursor cursor ( void ) const { return FL_CURSOR_CROSS; }
|
||||||
|
|
||||||
curve_type_e interpolation ( void ) const { return _interpolation; }
|
Curve_Type interpolation ( void ) const { return _interpolation; }
|
||||||
void interpolation ( curve_type_e v ) { _interpolation = v; }
|
void interpolation ( Curve_Type v ) { _interpolation = v; }
|
||||||
int frequency ( void ) const { return _frequency; }
|
|
||||||
void frequency ( int v ) { _frequency = v; _interval = ( 1.0f / (float)v ) / 2; }
|
Mode mode ( void ) const { return _mode; }
|
||||||
|
void mode ( Mode v );
|
||||||
|
|
||||||
/* Engine */
|
/* Engine */
|
||||||
void output ( JACK::Port *p ) { _output = p; }
|
void output ( JACK::Port *p ) { _output = p; }
|
||||||
|
|
|
@ -97,7 +97,10 @@ nframes_t
|
||||||
Control_Sequence::process ( nframes_t nframes )
|
Control_Sequence::process ( nframes_t nframes )
|
||||||
{
|
{
|
||||||
THREAD_ASSERT( RT );
|
THREAD_ASSERT( RT );
|
||||||
|
|
||||||
|
if ( ! _output )
|
||||||
|
return nframes;
|
||||||
|
|
||||||
if ( _output->connected() ) /* don't waste CPU on disconnected ports */
|
if ( _output->connected() ) /* don't waste CPU on disconnected ports */
|
||||||
{
|
{
|
||||||
void *buf = _output->buffer( nframes );
|
void *buf = _output->buffer( nframes );
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "TLE.H"
|
#include "TLE.H"
|
||||||
#include "NSM.H"
|
#include "NSM.H"
|
||||||
#include "Project.H"
|
#include "Project.H"
|
||||||
|
#include "OSC/Endpoint.H"
|
||||||
|
|
||||||
#define OSC_INTERVAL 0.2f
|
#define OSC_INTERVAL 0.2f
|
||||||
|
|
||||||
|
@ -60,28 +61,32 @@ NSM_Client::command_open ( const char *name, const char *display_name, const cha
|
||||||
|
|
||||||
timeline->osc->name( client_id );
|
timeline->osc->name( client_id );
|
||||||
|
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
if ( Project::validate( name ) )
|
if ( Project::validate( name ) )
|
||||||
{
|
{
|
||||||
if ( timeline->command_load( name, display_name ) )
|
if ( timeline->command_load( name, display_name ) )
|
||||||
return ERR_OK;
|
r = ERR_OK;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*out_msg = strdup( "Failed to load for unknown reason" );
|
*out_msg = strdup( "Failed to load for unknown reason" );
|
||||||
return ERR_GENERAL;
|
r = ERR_GENERAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( timeline->command_new( name, display_name ) )
|
if ( timeline->command_new( name, display_name ) )
|
||||||
return ERR_OK;
|
r =ERR_OK;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*out_msg = strdup( "Failed to load for unknown reason" );
|
*out_msg = strdup( "Failed to load for unknown reason" );
|
||||||
return ERR_GENERAL;
|
r = ERR_GENERAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
timeline->discover_peers();
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
#include "OSC_Thread.H"
|
#include "OSC_Thread.H"
|
||||||
|
#include "OSC/Endpoint.H"
|
||||||
|
|
||||||
#include "NSM.H"
|
#include "NSM.H"
|
||||||
extern NSM_Client *nsm;
|
extern NSM_Client *nsm;
|
||||||
|
@ -1528,9 +1529,7 @@ Timeline::command_load ( const char *name, const char *display_name )
|
||||||
|
|
||||||
Project::set_name ( display_name ? display_name : name );
|
Project::set_name ( display_name ? display_name : name );
|
||||||
|
|
||||||
// discover_peers();
|
return true;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -1553,9 +1552,7 @@ Timeline::command_new ( const char *name, const char *display_name )
|
||||||
|
|
||||||
/* tle->main_window->redraw(); */
|
/* tle->main_window->redraw(); */
|
||||||
|
|
||||||
// discover_peers();
|
return b;
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
@ -1597,6 +1594,8 @@ Timeline::init_osc ( const char *osc_port )
|
||||||
/* poll so we can keep OSC handlers running in the GUI thread and avoid extra sync */
|
/* poll so we can keep OSC handlers running in the GUI thread and avoid extra sync */
|
||||||
Fl::add_timeout( OSC_INTERVAL, &Timeline::check_osc, this );
|
Fl::add_timeout( OSC_INTERVAL, &Timeline::check_osc, this );
|
||||||
|
|
||||||
|
osc->signal_peer_scan_complete.connect( sigc::mem_fun( this, &Timeline::connect_osc ) );
|
||||||
|
|
||||||
if ( ! osc_thread )
|
if ( ! osc_thread )
|
||||||
{
|
{
|
||||||
osc_thread = new OSC_Thread();
|
osc_thread = new OSC_Thread();
|
||||||
|
@ -1619,14 +1618,11 @@ Timeline::osc_non_hello ( const char *path, const char *types, lo_arg **argv, in
|
||||||
const char *version = &argv[2]->s;
|
const char *version = &argv[2]->s;
|
||||||
const char *id = &argv[3]->s;
|
const char *id = &argv[3]->s;
|
||||||
|
|
||||||
MESSAGE( "Discovered OSC peer %s (%s) @ %s with ID \"%s\"", name, version, url, id );
|
MESSAGE( "Discovered NON peer %s (%s) @ %s with ID \"%s\"", name, version, url, id );
|
||||||
|
MESSAGE( "Registering Signals" );
|
||||||
MESSAGE( "Scanning..." );
|
|
||||||
|
|
||||||
// timeline->osc->scan_peer( id, url );
|
|
||||||
|
|
||||||
timeline->osc->hello( url );
|
timeline->osc->hello( url );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1673,24 +1669,17 @@ Timeline::connect_osc ( void )
|
||||||
void
|
void
|
||||||
Timeline::discover_peers ( void )
|
Timeline::discover_peers ( void )
|
||||||
{
|
{
|
||||||
lo_message m = lo_message_new();
|
if ( nsm->is_active() )
|
||||||
|
{
|
||||||
|
lo_message m = lo_message_new();
|
||||||
|
|
||||||
|
lo_message_add_string( m, "/non/finger" );
|
||||||
|
lo_message_add_string( m, osc->url() );
|
||||||
|
|
||||||
lo_message_add_string( m, "/non/finger" );
|
nsm->broadcast( m );
|
||||||
lo_message_add_string( m, osc->url() );
|
|
||||||
|
lo_message_free( m );
|
||||||
nsm->broadcast( m );
|
}
|
||||||
|
|
||||||
lo_message_free( m );
|
|
||||||
|
|
||||||
/* wait for responses and then autoconnect outputs */
|
|
||||||
|
|
||||||
MESSAGE( "Waiting for OSC peers..." );
|
|
||||||
|
|
||||||
osc->wait( 1000 );
|
|
||||||
|
|
||||||
MESSAGE( "Reconnecting signals." );
|
|
||||||
|
|
||||||
connect_osc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "OSC/Endpoint.H"
|
|
||||||
#include "OSC_Thread.H"
|
#include "OSC_Thread.H"
|
||||||
|
|
||||||
class Fl_Scroll;
|
class Fl_Scroll;
|
||||||
|
@ -54,6 +53,10 @@ class Scalebar;
|
||||||
class Sequence;
|
class Sequence;
|
||||||
class Sequence_Widget;
|
class Sequence_Widget;
|
||||||
|
|
||||||
|
namespace OSC { class Endpoint; }
|
||||||
|
|
||||||
|
#include <lo/lo.h>
|
||||||
|
|
||||||
#ifndef USE_SINGLEBUFFERED_TIMELINE
|
#ifndef USE_SINGLEBUFFERED_TIMELINE
|
||||||
#include <FL/Fl_Overlay_Window.H>
|
#include <FL/Fl_Overlay_Window.H>
|
||||||
#else
|
#else
|
||||||
|
@ -236,8 +239,6 @@ public:
|
||||||
|
|
||||||
/* OSC */
|
/* OSC */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void connect_osc ( void );
|
void connect_osc ( void );
|
||||||
|
|
||||||
void discover_peers ( void );
|
void discover_peers ( void );
|
||||||
|
|
Loading…
Reference in New Issue