Update NTK.
[nondaw.git] / nonlib / OSC / Endpoint.C
blobde2e7be57da009a9d1bb429f796c6179834e99a8
2 /*******************************************************************************/
3 /* Copyright (C) 2010 Jonathan Moore Liles                                     */
4 /*                                                                             */
5 /* This program is free software; you can redistribute it and/or modify it     */
6 /* under the terms of the GNU General Public License as published by the       */
7 /* Free Software Foundation; either version 2 of the License, or (at your      */
8 /* option) any later version.                                                  */
9 /*                                                                             */
10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       */
12 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   */
13 /* more details.                                                               */
14 /*                                                                             */
15 /* You should have received a copy of the GNU General Public License along     */
16 /* with This program; see the file COPYING.  If not,write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18 /*******************************************************************************/
20 #include <lo/lo.h>
21 #include "debug.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <assert.h>
27 #include "Endpoint.H"
29 #include "Thread.H"
31 #pragma GCC diagnostic ignored "-Wunused-parameter"
33 namespace OSC
36     /**********/
37     /* Method */
38     /**********/
40     Method::Method ( )
41     {
42         _path = _typespec = _documentation = 0;
43     }
44     
45     Method::~Method ( )
46     {
47         if ( _path )
48             free( _path );
49         if ( _typespec )
50             free( _typespec );
51     }
53     /**********/
54     /* Signal */
55     /**********/
57     int Signal::next_id = 0;
60     Signal::Signal ( const char *path, Direction dir )
61     { 
62         _direction = dir;
63         _path = strdup( path );
64         _id = ++next_id;
65         _value = 0.0f;
66         _endpoint = NULL;
67         _peer = NULL;
68         _documentation = 0;
69         _user_data = 0;
70         _connection_state_callback = 0;
71         _connection_state_userdata = 0;
72     }
74     Signal::~Signal ( )
75     {
76         if ( _endpoint )
77         {
78             _endpoint->del_signal( this );
79         }
80                 
81         free( _path );
82         _path = NULL;
84         _endpoint = NULL;
85     }
87     void
88     Signal::rename ( const char *path )
89     {
90         DMESSAGE( "Renaming signal %s to %s", this->path(), path );
92         free( _path );
93         _path = strdup( path );
95         _endpoint->send_signal_rename_notifications( this );
96     }
98     bool
99     Signal::is_connected_to ( const OSC::Signal *s ) const
100     {
101         for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
102               i != _outgoing.end();
103               ++i )
104         {
105             if ( (*i)->_peer == s->_peer &&
106                  (*i)->id() == s->id() )
107                 return true;
108         }
110         return false;
111     }
112     
113     void
114     Signal::value ( float f )
115     {
116         for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
117               i != _outgoing.end();
118               ++i )
119         {
120             /* FIXME: won't work for loopback */
121             if ( (*i)->_value != f )
122             {
123                 (*i)->_value = f;
125                 _endpoint->send( (*i)->_peer->addr, 
126                                  "/signal/change",
127                                  id(),
128                                  (*i)->id(),
129                                  f );
130             }
131         }
132     }
134     char *
135     Signal::get_output_connection_peer_name_and_path ( int n )
136     {
137         Signal *t;
139         int j = 0;
140         for ( std::list<Signal*>::const_iterator i = _outgoing.begin();
141               i != _outgoing.end();
142               ++i, ++j )
143         {
144             if ( j == n )
145             {
146                 t = *i;
147                 break;
148             }
149         }
151 //        Signal *s = get_peer_signal_by_id( t->_peer, t->signal_id );
153         char *r;
154         asprintf( &r, "%s:%s", t->_peer->name, t->path() );
156         return r;
157     }
161     void
162     Endpoint::error_handler(int num, const char *msg, const char *path)
163     {
164         WARNING( "LibLO server error %d in path %s: %s\n", num, path, msg);
165     }
167     Endpoint::Endpoint ( )
168     {
169         _peer_scan_complete_callback = 0;
170         _peer_scan_complete_userdata = 0;
171         _server = 0;
172         _name = 0;
173         owner = 0;
174     }
176     int
177     Endpoint::init ( int proto, const char *port )
178     {
179         DMESSAGE( "Creating OSC server" );
181         _server = lo_server_new_with_proto( port, proto, error_handler );
183         if ( ! _server )
184         {
185             WARNING( "Error creating OSC server" );
186             return -1;
187         }
189         add_method( "/signal/hello", "ss", &Endpoint::osc_sig_hello, this, "" );
190         add_method( "/signal/connect", "ii", &Endpoint::osc_sig_connect, this, "" );
191         add_method( "/signal/disconnect", "ii", &Endpoint::osc_sig_disconnect, this, "" );
192         add_method( "/signal/renamed", "is", &Endpoint::osc_sig_renamed, this, "" );
193         add_method( "/signal/removed", "i", &Endpoint::osc_sig_removed, this, "" );
194         add_method( "/signal/created", "ssifff", &Endpoint::osc_sig_created, this, "" );
195         add_method( "/signal/change", "iif", &Endpoint::osc_sig_handler, this, "" );
196         add_method( "/signal/list", NULL, &Endpoint::osc_signal_lister, this, "" );
197         add_method( NULL, "", &Endpoint::osc_generic, this, "" );
198         add_method( "/reply", NULL, &Endpoint::osc_reply, this, "" );
200         return 0;
201     }
204     Endpoint::~Endpoint ( )
205     {
206 //    lo_server_thread_free( _st );
207         if ( _server )
208         {
209             lo_server_free( _server );
210             _server = 0;
211         }
212     }
214     OSC::Signal *
215     Endpoint::find_target_by_peer_address ( std::list<Signal*> *l, lo_address addr )
216     {
218         for ( std::list<Signal*>::iterator i = l->begin();
219               i != l->end();
220               ++i )
221         {
222             if ( address_matches( addr, (*i)->_peer->addr ) )
223             {
224                 return *i;
225             }
226         }
228         return NULL;
229     }
231     OSC::Signal *
232     Endpoint::find_signal_by_id ( int id )
233     {
234         for ( std::list<Signal*>::iterator i = _signals.begin();
235               i != _signals.end();
236               ++i )
237         {
238             if ( (*i)->id() == id )
239                 return *i;
240         }
242         return NULL;
243     }
245     OSC::Signal *
246     Endpoint::find_peer_signal_by_path ( Peer *p, const char *path )
247     {
248         for ( std::list<Signal*>::iterator i = p->_signals.begin();
249               i != p->_signals.end();
250               ++i )
251         {
252             if ( !strcmp( (*i)->path(), path ) )
253                 return *i;
254         }
256         return NULL;
257     }
259     OSC::Signal *
260     Endpoint::find_peer_signal_by_id ( Peer *p, int id )
261     {
262         for ( std::list<Signal*>::iterator i = p->_signals.begin();
263               i != p->_signals.end();
264               ++i )
265         {
266             if ( id == (*i)->id() )
267                 return *i;
268         }
270         return NULL;
271     }
273     void
274     Endpoint::hello ( const char *url )
275     {
276         assert( name() );
278         lo_address addr = lo_address_new_from_url ( url );
280         char *our_url = this->url();
281         send( addr, "/signal/hello", name(), our_url );
282         free( our_url );
283         
284         lo_address_free( addr );
285     }
287     int
288     Endpoint::osc_sig_hello ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
289     {
291         Endpoint *ep = (Endpoint*)user_data;
293         const char *peer_name = &argv[0]->s;
294         const char *peer_url = &argv[1]->s;
295         
296         DMESSAGE( "Got hello from %s", peer_name );
298         if ( ! ep->find_peer_by_name( peer_name ) )
299         {
300             ep->scan_peer( peer_name, peer_url );
302             if ( ep->name() )
303             {
304                 ep->hello( peer_url );
305             }
306             else
307             {
308                 DMESSAGE( "Not sending hello because we don't have a name yet!" );
309             }
310         }
312         return 0;
313     }
315     int
316     Endpoint::osc_sig_disconnect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
317     {
318         int their_id = argv[0]->i;
319         int our_id = argv[1]->i;
320      
321         Endpoint *ep = (Endpoint*)user_data;
323         Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
325         if ( ! p )
326             return 0;
328         Signal *ps = ep->find_peer_signal_by_id( p, their_id );
330         if ( ! ps )
331             return 0;
333         Signal *s = ep->find_signal_by_id( our_id );
335         if ( ! s )
336             return 0;
338         if ( s->_direction == Signal::Input )
339         {
340             s->_incoming.remove( ps );
341             
342             DMESSAGE( "Peer %s has disconnected from signal %s", p->name, ps->path() );
344             if ( s->_connection_state_callback )
345                 s->_connection_state_callback( s, s->_connection_state_userdata );
347             return 0;
348         }
350         return 0;
351     }
354     int
355     Endpoint::osc_sig_connect ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
356     {
357         int their_id = argv[0]->i;
358         int our_id = argv[1]->i;
359      
360         Endpoint *ep = (Endpoint*)user_data;
362         Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
364         if ( ! p )
365         {
366             WARNING( "Got connection signal from unknown peer" );
367             return 0;
368         }
370         Signal *ps = ep->find_peer_signal_by_id( p, their_id );
372         if ( ! ps )
373         {
374             WARNING( "Unknown source signal" );
376             return 0;
377         }
379         Signal *s = ep->find_signal_by_id( our_id );
381         if ( ! s )
382         {
383             WARNING( "Unknown destination signal" );
385             return 0;
386         }
388         DMESSAGE( "Peer %s has connected to signal %s", p->name, s->path() );
390         /* if ( s->_direction == Signal::Input ) */
391         /* { */
392         s->_incoming.push_back( ps );
394         /* make a record of it ourselves */
395         ps->_outgoing.push_back( s );
397         if ( s->_connection_state_callback )
398             s->_connection_state_callback( s, s->_connection_state_userdata );
400         /*     return 0; */
401         /* } */
403         return 0;
404     }
406     int
407     Endpoint::osc_sig_removed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
408     {
409         int id = argv[0]->i;
410         
411         Endpoint *ep = (Endpoint*)user_data;
412         
413         Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
414         
415         if ( ! p )
416         {
417             WARNING( "Got signal remove notification from unknown peer." );
418             return 0;
419         }
421         Signal *o = ep->find_peer_signal_by_id( p, id );
423         if ( ! o )
424         {
425             WARNING( "Unknown signal id %i", id );
426             return 0;
427         }
429         DMESSAGE( "Signal %s:%s was removed", o->_peer->name, o->path() );
431         /* disconnect it */
432         for ( std::list<Signal*>::iterator i = o->_outgoing.begin();
433               i != o->_outgoing.end();
434               ++i )
435         {
436             ep->disconnect_signal( o, *i );
437         }
439         for ( std::list<Signal*>::iterator i = o->_incoming.begin();
440               i != o->_incoming.end();
441               ++i )
442         {
443             ep->disconnect_signal( *i, o );
444         }
446         p->_signals.remove( o );
448         delete o;
450         return 0;
451     }
453     int
454     Endpoint::osc_sig_created ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
455     {
456         Endpoint *ep = (Endpoint*)user_data;
458         Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
460         if ( ! p )
461         {
462             WARNING( "Got signal creation from unknown peer." );
463             return 0;
464         }
465         
466         const char *name = &argv[0]->s;
467         const char *direction = &argv[1]->s;
468         const int id = argv[2]->i;
469         const float min = argv[3]->f;
470         const float max = argv[4]->f;
471         const float default_value = argv[5]->f;
473         DMESSAGE( "Peer %s has created signal %s with id %i (%s %f %f %f)", p->name, 
474                   name, id, direction, min, max, default_value );
475         
476         Signal::Direction dir = Signal::Input;
477         
478         if ( !strcmp( direction, "in" ) )
479             dir = Signal::Input;
480         else if ( !strcmp( direction, "out" ) )
481             dir = Signal::Output;
482         
483         Signal *s = new Signal( name, dir );
484         
485         s->_peer = p;
486         s->_id = id;
487         s->parameter_limits( min, max, default_value );
488         
489         p->_signals.push_back( s );
490         
491         return 0;
492     }
494     int
495     Endpoint::osc_sig_renamed ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
496     {
497         DMESSAGE( "Got renamed message." );
499         int id = argv[0]->i;
500         char *new_name = &argv[1]->s;
502         Endpoint *ep = (Endpoint*)user_data;
504         Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
505         
506         if ( ! p )
507         {
508             WARNING( "Got signal rename notification from unknown peer." );
509             return 0;
510         }
512         Signal *o = ep->find_peer_signal_by_id( p, id );
514         if ( ! o )
515         {
516             WARNING( "Unknown signal id %i", id );
517             return 0;
518         }
520         DMESSAGE( "Signal %s:%s was renamed to %s", o->_peer->name, o->_path, path );
521         
522         free( o->_path );
523         o->_path = strdup( new_name );
525         return 0;
526     }
528     int
529     Endpoint::osc_sig_handler ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
530     {
531         Signal *o;
532         float f = 0.0;
533         Endpoint *ep = NULL;
536         if ( !strcmp( path, "/signal/change" ) && !strcmp( types, "iif" ) )
537         {
538             /* accept a value for numbered signal */
539             int id = argv[1]->i;
540             f = argv[2]->f;
541             ep = (Endpoint*)user_data;
543             o = ep->find_signal_by_id( id );
545             if ( ! o )
546             {
547                 WARNING( "Unknown signal id %i", id );
548                 return 0;
549             }
550         }
551         else if ( ! strcmp( types, "f" ) )
552         {
553             /* accept a value for signal named in path */
554             o = (Signal*)user_data;
555             f = argv[0]->f;
556         }
557         else if ( ! types || 0 == types[0] )
558         {
559             /* reply with current value */
560             o = (Signal*)user_data;
561             o->_endpoint->send( lo_message_get_source( msg ), "/reply", path, o->value() );
562             return 0;
563         }
564         else
565         {
566             return -1;
567         }
569         Peer *p = NULL;
571         if ( ep )
572             p = ep->find_peer_by_address( lo_message_get_source( msg ) );
575         if ( !p )
576         {
577             DMESSAGE( "Signal change initiated by an unknown peer" );
578             /* message came from an unconnected peer, just set the value exactly */
579         }
580         else
581         {
582             /* message is from a connected source, do mixing. */
584             /* remote signal */
585             /* if ( t->_peer ) */
587             /* if ( 0 == o->_incoming.size() ) */
588             /*     return 0; */
590             for ( std::list<Signal*>::const_iterator i = o->_incoming.begin();
591                   i != o->_incoming.end();
592                   ++i )
593             {
594                 if ( (*i)->id() == argv[0]->i )
595                 {
596                     (*i)->_value = f;
597                     break;
598                 }
599             }
601             f = 0.0;
603             for ( std::list<Signal*>::const_iterator i = o->_incoming.begin();
604                   i != o->_incoming.end();
605                   ++i )
606             {
607                 f += (*i)->_value;
608             }
609         }
611         o->_value = f;
613         o->_handler( f, o->_user_data );
614         
615         return 0;
616     }
618     int
619     Endpoint::osc_generic ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
620     {
621 //        OSC_DMSG();
623         if ( argc || path[ strlen(path) - 1 ] != '/' )
624             return -1;
626         Endpoint *ep = (Endpoint*)user_data;
628         for ( std::list<Method*>::const_iterator i = ep->_methods.begin(); i != ep->_methods.end(); ++i )
629         {
630             if ( ! (*i)->path() )
631                 continue;
633             if (! strncmp( (*i)->path(), path, strlen(path) ) )
634             {
635                 /* asprintf( &stored_path, "%s (%s); %s", path, typespec, argument_description ); */
637                 ((Endpoint*)user_data)->send( lo_message_get_source( msg ), "/reply", path, (*i)->path() );
638             }
639         }
641         ((Endpoint*)user_data)->send( lo_message_get_source( msg ), "/reply", path );
643         return 0;
644     }
646     int
647     Endpoint::osc_signal_lister ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
648     {
649 //        OSC_DMSG();
651         const char *prefix = NULL;
653         if ( argc )
654             prefix = &argv[0]->s;
656         Endpoint *ep = (Endpoint*)user_data;
658         for ( std::list<Signal*>::const_iterator i = ep->_signals.begin(); i != ep->_signals.end(); ++i )
659         {
660             Signal *o = *i;
662             if ( ! prefix || ! strncmp( o->path(), prefix, strlen(prefix) ) )
663             {
664                 ep->send( lo_message_get_source( msg ),
665                           "/reply", 
666                           path,
667                           o->path(),
668                           o->_direction == Signal::Input ? "in" : "out",
669                           o->id(),
670                           o->parameter_limits().min,
671                           o->parameter_limits().max,
672                           o->parameter_limits().default_value
673                     );
674             }
675         }
676         
677         ep->send( lo_message_get_source( msg ), "/reply", path );
679         return 0;
680     }
682     bool
683     Endpoint::address_matches ( lo_address addr1, lo_address addr2 )
684     {
685         char *purl = strdup( lo_address_get_port( addr1 ) );
686         char *url = strdup( lo_address_get_port( addr2 ) );
688         bool r = !strcmp( purl, url );
690         free( purl );
691         free( url );
692         
693         return r;
694     }
697     void
698     Endpoint::list_peer_signals ( void (*callback) (const char *, const OSC::Signal *, void * ), void *v )
699     {
700         for ( std::list<Peer*>::iterator i = _peers.begin(); 
701               i != _peers.end();
702               ++i )
703         {
704             for ( std::list<Signal*>::iterator j = (*i)->_signals.begin(); 
705                   j != (*i)->_signals.end();
706                   ++j )
707             {
708 //                DMESSAGE( "Running callback" );
709                 callback( (*i)->name, *j, v );
710             }
711         }
712     }
714     Peer *
715     Endpoint::find_peer_by_address ( lo_address addr )
716     {
717         char *url = strdup( lo_address_get_port( addr ) );
719         Peer *p = NULL;
721         for ( std::list<Peer*>::iterator i = _peers.begin(); 
722               i != _peers.end();
723               ++i )
724         {
725             char *purl = strdup( lo_address_get_port( (*i)->addr ) );
727             if ( !strcmp( purl, url ) )
728             {
729                 free( purl );
730                 p = *i;
731                 break;
732             }
733             free(purl);
734         }
736         free( url );
738         return p;
739     }
741     Peer *
742     Endpoint::find_peer_by_name ( const char *name )
743     {
744         for ( std::list<Peer*>::iterator i = _peers.begin(); 
745               i != _peers.end();
746               ++i )
747         {
748             if ( !strcmp( name, (*i)->name ) )
749             {
750                 return *i;
751             }
752         }
754         return NULL;
755     }
757     bool
758     Endpoint::disconnect_signal ( OSC::Signal *s, OSC::Signal *d )
759     {
760         if ( ! s->is_connected_to( d ) )
761             return false;
763         MESSAGE( "Disconnecting signal output \"%s\" to %s:%i", s->path(), d->_peer->name, d->_id );
764         
765         send( d->_peer->addr, "/signal/disconnect", 
766               s->_id, /* our signal id */
767               d->_id  /* their signal id */ );
768         
769         s->_outgoing.remove( d );
770         s->_incoming.remove( d );
772         return true;
773     }
775     bool
776     Endpoint::disconnect_signal ( OSC::Signal *s, const char *peer_name, const char *signal_path )
777     {
778         if ( s->_direction == Signal::Output )
779         {
780             Peer *p = find_peer_by_name( peer_name );
781             
782             if ( ! p )
783                 return false;
785             Signal *ps = find_peer_signal_by_path( p, signal_path );
786             
787             if ( ! ps )
788                 return false;
790             if ( ! s->is_connected_to( ps ) )
791                 return false;
793             return disconnect_signal( s, ps );     
794         }
796         return false;
797     }
799     bool
800     Endpoint::connect_signal( OSC::Signal *s, const char *peer_and_path )
801     {
802         char peer[512];
803         char path[1024];
805         /* FIXME: use %a */
806         if ( 2 == sscanf( peer_and_path, "%[^:]:%s", peer, path ) )
807         {
808             return connect_signal( s, peer, path );
809         }
810         else
811             return false;
812     }
814     bool
815     Endpoint::connect_signal ( OSC::Signal *s, OSC::Signal *d )
816     {
817         if ( s->is_connected_to( d ) )
818         {
819             return false;
820         }
821         
822         MESSAGE( "Connecting signal output \"%s\" to %s:%s", s->path(), d->_peer->name, d->path() );
823         
824         s->_outgoing.push_back( d );
826         /* make a record of it ourselves */
827         d->_incoming.push_back( s );
828         
829         send( d->_peer->addr, "/signal/connect", 
830               s->_id, /* our signal id */
831               d->_id /* their signal id */ );
832         
833         return true;
834     }
836   
837     bool
838     Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, const char *signal_path )
839     {
840         if ( s->_direction == Signal::Output )
841         {
842             Peer *p = find_peer_by_name( peer_name );
843             
844             if ( ! p )
845                 return false;
847             Signal *ps = find_peer_signal_by_path( p, signal_path );
848             
849             if ( ! ps )
850                 return false;
852             return connect_signal( s, ps );
853         }
855         return false;
856     }
858     bool
859     Endpoint::connect_signal( OSC::Signal *s, const char *peer_name, int signal_id )
860     {
861         if ( s->_direction == Signal::Output )
862         {
863             Peer *p = find_peer_by_name( peer_name );
865             if ( !p )
866                 return false;
868             Signal *ps = find_peer_signal_by_id( p, signal_id );
870             if ( !ps )
871                 return false;
873             return connect_signal( s, ps );
874         }            
875     
876         return false;
877     }
879     Signal *
880     Signal::get_peer_signal_by_id ( Peer *p, int signal_id )
881     {
882         for ( std::list<Signal *>::iterator i = p->_signals.begin();
883               i != p->_signals.end();
884               ++i )
885         {
886             if ( (*i)->_id == signal_id )
887                 return *i;
888         }
889         
890         return NULL;
891     }
893     int
894     Endpoint::osc_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
895         
896     {
897         Endpoint *ep = (Endpoint*)user_data;
899         if ( argc && !strcmp( &argv[0]->s, "/signal/list" ) )
900         {
901             Peer *p = ep->find_peer_by_address( lo_message_get_source( msg ) );
903             if ( ! p )
904             {
905                 WARNING( "Got input list reply from unknown peer." );
906                 return 0;
907             }
909             if ( argc == 1 )
910             {
911                 p->_scanning = false;
912                 DMESSAGE( "Done scanning %s", p->name );
914                 if ( ep->_peer_scan_complete_callback )
915                     ep->_peer_scan_complete_callback(ep->_peer_scan_complete_userdata);
916             }
917             else if ( argc == 7 && p->_scanning )
918             {
919                 DMESSAGE( "Peer %s has signal %s (%s)", p->name, &argv[1]->s, &argv[2]->s );
921                 int dir = 0;
923                 if ( !strcmp( &argv[2]->s, "in" ) )
924                     dir = Signal::Input;
925                 else if ( !strcmp( &argv[2]->s, "out" ) )
926                     dir = Signal::Output;
928                 Signal *s = new Signal( &argv[1]->s, (Signal::Direction)dir );
929                 
930                 s->_peer = p;
931                 s->_id = argv[3]->i;
932                 s->parameter_limits( argv[4]->f, argv[5]->f, argv[6]->f );
934                 p->_signals.push_back( s );
935             }
937             return 0;
938         }
939         else
940             return -1;
941     }
943     Method *
944     Endpoint::add_method ( const char *path, const char *typespec, lo_method_handler handler, void *user_data, const char *argument_description )
945     {
946 //      DMESSAGE( "Added OSC method %s (%s)", path, typespec );
948         lo_server_add_method( _server, path, typespec, handler, user_data );
950         Method *md = new Method;
951         
952         if ( path )
953             md->_path = strdup( path );
954         if ( typespec )
955             md->_typespec = strdup( typespec );
956         if ( argument_description )
957             md->_documentation = strdup( argument_description );
958         
959         _methods.push_back( md );
961         return md;
962     }
964     Signal *
965     Endpoint::add_signal ( const char *path, Signal::Direction dir, float min, float max, float default_value, signal_handler handler, void *user_data )
966     {
967         Signal *o = new Signal( path, dir );
968         
969         if ( path )
970             o->_path = strdup( path );
971         
972         o->_handler = handler;
973         o->_user_data = user_data;
974         o->_endpoint = this;
975         
976         _signals.push_back( o );
977         
978         if ( dir == Signal::Input )
979         {
980             lo_server_add_method( _server, path, NULL, osc_sig_handler, o );
981         }
984         o->parameter_limits( min, max, default_value );
986         /* tell our peers about it */
987         for ( std::list<Peer*>::iterator i = _peers.begin();
988               i != _peers.end();
989               ++i )
990         {
991             send( (*i)->addr,
992                   "/signal/created", 
993                   o->path(),
994                   o->_direction == Signal::Input ? "in" : "out",
995                   o->id(),
996                   min,
997                   max,
998                   default_value
999                 );
1000         }
1002         return o;
1003     }
1005     void
1006     Endpoint::del_method ( const char *path, const char *typespec )
1007     {
1008 //      DMESSAGE( "Deleted OSC method %s (%s)", path, typespec );
1010         lo_server_del_method( _server, path, typespec );
1012         for ( std::list<Method *>::iterator i = _methods.begin(); i != _methods.end(); ++i )
1013         {
1014             if ( ! (*i)->path() )
1015                 continue;
1017             if ( ! strcmp( path, (*i)->path() ) &&
1018                  ! strcmp( typespec, (*i)->typespec() ) )
1019             {
1020                 delete *i;
1021                 i = _methods.erase( i );
1023                 break;
1024             }
1025         }
1026     }
1028     void
1029     Endpoint::del_method ( Method *meth )
1030     {
1031 //      DMESSAGE( "Deleted OSC method %s (%s)", path, typespec );
1033         lo_server_del_method( _server, meth->path(), meth->typespec() );
1035         delete meth;
1037         _methods.remove( meth );
1038     }
1040     void
1041     Endpoint::send_signal_rename_notifications ( Signal *s )
1042     {
1043     
1044         for ( std::list<Peer*>::const_iterator i = _peers.begin();
1045               i != _peers.end();
1046               ++i )
1047         {
1048             send( (*i)->addr, 
1049                   "/signal/renamed",
1050                   s->id(),
1051                   s->path() );
1052         }
1053     }
1055     void
1056     Endpoint::del_signal ( Signal *o )
1057     {
1058 //      DMESSAGE( "Deleted OSC method %s (%s)", path, typespec );
1060         lo_server_del_method( _server, o->path(), "f" );
1062         /* tell our peers about it */
1063         for ( std::list<Peer*>::iterator i = _peers.begin();
1064               i != _peers.end();
1065               ++i )
1066         {
1067             send( (*i)->addr,
1068                   "/signal/removed", 
1069                   o->id() );
1070         }
1072         /* FIXME: clear loopback connections first! */
1073 //        delete o;
1075         _signals.remove( o );
1076     }
1078     void
1079     Endpoint::scan_peer ( const char *name, const char *url )
1080     {
1081         Peer *p = new Peer;
1083         DMESSAGE( "Scanning peer %s @ %s...", name, url );
1085         p->name = strdup( name );
1086         p->addr = lo_address_new_from_url( url );
1087         p->_scanning = true;
1089         _peers.push_back( p );
1091         send( p->addr, "/signal/list" );
1092     }
1094     void *
1095     Endpoint::osc_thread ( void * arg )
1096     {
1097         ((Endpoint*)arg)->osc_thread();
1099         return NULL;
1100     }
1102     void
1103     Endpoint::osc_thread ( void )
1104     {
1105         _thread.name( "OSC" );
1107         DMESSAGE( "OSC Thread running" );
1108         
1109         run();
1110     }
1112     void
1113     Endpoint::start ( void )
1114     {
1116         if ( !_thread.clone( &Endpoint::osc_thread, this ) )
1117             FATAL( "Could not create OSC thread" );
1119 /*      lo_server_thread_start( _st ); */
1121     }
1123     void
1124     Endpoint::stop ( void )
1125     {
1126         _thread.join();
1127 //    lo_server_thread_stop( _st );
1128     }
1130     int
1131     Endpoint::port ( void ) const
1132     {
1133         return lo_server_get_port( _server );
1134     }
1136     char *
1137     Endpoint::url ( void ) const
1138     {
1139         return lo_server_get_url( _server );
1140     }
1142 /** Process any waiting events and return immediately */
1143     void
1144     Endpoint::check ( void ) const
1145     {
1146         wait( 0 );
1147     }
1149 /** Process any waiting events and return after timeout */
1150     void
1151     Endpoint::wait ( int timeout ) const
1152     {
1153         if ( lo_server_wait( _server, timeout ) )
1154             while ( lo_server_recv_noblock( _server, 0 ) ) { }
1155     }
1157 /** Process events forever */
1158     void
1159     Endpoint::run ( void ) const
1160     {
1161         for ( ;; )
1162         {
1163             lo_server_recv( _server );
1164         }
1165     }
1167     int
1168     Endpoint::send ( lo_address to, const char *path, std::list< OSC_Value > values )
1169     {
1171         lo_message m = lo_message_new();
1173         for ( std::list< OSC_Value >::const_iterator i = values.begin();
1174               i != values.end();
1175               ++i )
1176         {
1177             const OSC_Value *ov = &(*i);
1179             switch ( ov->type() )
1180             {
1181                 case 'f':
1182                     DMESSAGE( "Adding float %f", ((OSC_Float*)ov)->value() );
1183                     lo_message_add_float( m, ((OSC_Float*)ov)->value() );
1184                     break;
1185                 case 'i':
1186                     DMESSAGE( "Adding int %i", ((OSC_Int*)ov)->value() );
1187                     lo_message_add_int32( m, ((OSC_Int*)ov)->value() );
1188                     break;
1189                 case 's':
1190                     DMESSAGE( "Adding string %s", ((OSC_String*)ov)->value() );
1191                     lo_message_add_string( m, ((OSC_String*)ov)->value() );
1192                     break;
1193                 default:
1194                     FATAL( "Unknown format: %c", ov->type() );
1195                     break;
1196             }
1197         }
1199         DMESSAGE( "Path: %s", path );
1201         lo_bundle b = lo_bundle_new( LO_TT_IMMEDIATE );
1203         lo_bundle_add_message(b, path, m );
1205         int r = lo_send_bundle_from( to, _server, b );
1207 //    int r = lo_send_message_from( to, _server, path, m );
1209 //    lo_message_free( m );
1211         return r;
1212     }
1214     int
1215     Endpoint::send ( lo_address to, const char *path )
1216     {
1217         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "" );
1218     }
1220     int
1221     Endpoint::send ( lo_address to, const char *path, int v )
1222     {
1223         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "i", v );
1224     }
1226     int
1227     Endpoint::send ( lo_address to, const char *path, float v )
1228     {
1229         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "f", v );
1230     }
1232     int
1233     Endpoint::send ( lo_address to, const char *path, double v )
1234     {
1235         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "d", v );
1236     }
1238     int
1239     Endpoint::send ( lo_address to, const char *path, const char * v )
1240     {
1241         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "s", v );
1242     }
1244     int
1245     Endpoint::send ( lo_address to, const char *path, const char * v1, float v2 )
1246     {
1247         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sf", v1, v2 );
1248     }
1250     int
1251     Endpoint::send ( lo_address to, const char *path, const char * v1, const char *v2 )
1252     {
1253         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ss", v1, v2 );
1254     }
1256     int
1257     Endpoint::send ( lo_address to, const char *path, const char * v1, const char *v2, const char *v3 )
1258     {
1259         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sss", v1, v2, v3 );
1260     }
1262     int
1263     Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3, int v4 )
1264     {
1265         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "siii", v1, v2, v3, v4 );
1266     }
1268     int
1269     Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, int v3, int v4, int v5 )
1270     {
1271         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssiii", v1, v2, v3, v4, v5 );
1272     }
1275     int
1276     Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, int v4, int v5, int v6 )
1277     {
1278         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssiii", v1, v2, v3, v4, v5, v6 );
1279     }
1281     int
1282     Endpoint::send ( lo_address to, const char *path, const char *v1, int v2 )
1283     {
1284         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "si", v1, v2 );
1285     }
1287     int
1288     Endpoint::send ( lo_address to, const char *path, int v1, const char *v2 )
1289     {
1290         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "is", v1, v2 );
1291     }
1293     int
1294     Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, const char *v3 )
1295     {
1296         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sis", v1, v2, v3 );
1297     }
1299     int
1300     Endpoint::send ( lo_address to, const char *path, int v1, const char *v2, const char *v3, const char *v4 )
1301     {
1302         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "isss", v1, v2, v3, v4 );
1303     }
1305     int
1306     Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, const char *v3, const char *v4, const char *v5 )
1307     {
1308         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sisss", v1, v2, v3, v4, v5 );
1309     }
1311     int
1312     Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, const char *v4, const char *v5 )
1313     {
1314         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssss", v1, v2, v3, v4, v5 );
1315     }
1317     int
1318     Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, const char *v3, const char *v4 )
1319     {
1320         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssss", v1, v2, v3, v4 );
1321     }
1323     int
1324     Endpoint::send ( lo_address to, const char *path, lo_message msg )
1325     {
1326         return lo_send_message_from( to, _server, path, msg );
1327     }
1329     int
1330     Endpoint::send ( lo_address to, const char *path, const char *v1, const char *v2, int v3, float v4, float v5, float v6 )
1331     {
1332         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ssifff", v1, v2, v3, v4, v5, v6 );
1333     }
1335     int
1336     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 )
1337     {
1338         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sssifff", v1, v2, v3, v4, v5, v6, v7 );
1339     }
1340     
1341     int
1342     Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3 )
1343     {
1344         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "sii", v1, v2, v3 );
1345     }
1347     int
1348     Endpoint::send ( lo_address to, const char *path, int v1, int v2 )
1349     {
1350         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "ii", v1, v2 );
1351     }
1353     int
1354     Endpoint::send ( lo_address to, const char *path, int v1, float v2 )
1355     {
1356         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "if", v1, v2 );
1357     }
1359     int
1360     Endpoint::send ( lo_address to, const char *path, const char *v1, int v2, int v3, float v4 )
1361     {
1362         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "siif", v1, v2, v3, v4 );
1363     }
1365     int
1366     Endpoint::send ( lo_address to, const char *path, int v1, int v2, float v3 )
1367     {
1368         return lo_send_from( to, _server, LO_TT_IMMEDIATE, path, "iif", v1, v2, v3 );
1369     }