merge with master and fix 4 conflicts by hand
[ardour.git] / libs / surfaces / osc / osc.cc
1 /*
2  * Copyright (C) 2006 Paul Davis
3  *  
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *  
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *  
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *  
18  */
19
20 #include <iostream>
21 #include <fstream>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <cerrno>
25 #include <algorithm>
26
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include <glib/gstdio.h>
31 #include <glibmm/miscutils.h>
32
33 #include <pbd/convert.h>
34 #include <pbd/pthread_utils.h>
35 #include <pbd/file_utils.h>
36 #include <pbd/failed_constructor.h>
37
38 #include "ardour/amp.h"
39 #include "ardour/session.h"
40 #include "ardour/route.h"
41 #include "ardour/audio_track.h"
42 #include "ardour/midi_track.h"
43 #include "ardour/dB.h"
44 #include "ardour/filesystem_paths.h"
45 #include "ardour/panner.h"
46 #include "ardour/plugin.h"
47 #include "ardour/send.h"
48
49 #include "osc.h"
50 #include "osc_controllable.h"
51 #include "osc_route_observer.h"
52 #include "i18n.h"
53
54 using namespace ARDOUR;
55 using namespace std;
56 using namespace Glib;
57
58 #include "pbd/abstract_ui.cc" // instantiate template
59
60 OSC* OSC::_instance = 0;
61
62 #ifdef DEBUG
63 static void error_callback(int num, const char *m, const char *path)
64 {
65         fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
66 }
67 #else
68 static void error_callback(int, const char *, const char *)
69 {
70
71 }
72 #endif
73
74 OSC::OSC (Session& s, uint32_t port)
75         : ControlProtocol (s, X_("Open Sound Control (OSC)"))
76         , AbstractUI<OSCUIRequest> ("osc")
77         , local_server (0)
78         , remote_server (0)
79         , _port(port)
80         , _ok (true)
81         , _shutdown (false)
82         , _osc_server (0)
83         , _osc_unix_server (0)
84         , _namespace_root ("/ardour")
85         , _send_route_changes (true)
86 {
87         _instance = this;
88
89         session_loaded (s);
90         session->Exported.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::session_exported, this, _1, _2), this);
91 }
92
93 OSC::~OSC()
94 {
95         stop ();
96         _instance = 0;
97 }
98
99 void
100 OSC::do_request (OSCUIRequest* req)
101 {
102         if (req->type == CallSlot) {
103
104                 call_slot (MISSING_INVALIDATOR, req->the_slot);
105
106         } else if (req->type == Quit) {
107
108                 stop ();
109         }
110 }
111
112 int
113 OSC::set_active (bool yn)
114 {
115         if (yn != active()) {
116
117                 if (yn) {
118                         if (start ()) {
119                                 return -1;
120                         }
121                 } else {
122                         if (stop ()) {
123                                 return -1;
124                         }
125                 }
126                 
127         }
128
129         return ControlProtocol::set_active (yn);
130 }
131
132 bool
133 OSC::get_active () const
134 {
135         return _osc_server != 0;
136 }
137
138 int 
139 OSC::set_feedback (bool yn)
140 {
141         _send_route_changes = yn;
142         return 0;
143 }
144
145 bool
146 OSC::get_feedback () const
147 {
148         return _send_route_changes;
149 }
150
151 int
152 OSC::start ()
153 {
154         char tmpstr[255];
155
156         if (_osc_server) {
157                 /* already started */
158                 return 0;
159         }
160         
161         for (int j=0; j < 20; ++j) {
162                 snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
163                 
164                 //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
165                 //      break;
166                 //}
167                 
168                 if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
169                         break;
170                 }
171
172 #ifdef DEBUG            
173                 cerr << "can't get osc at port: " << _port << endl;
174 #endif
175                 _port++;
176                 continue;
177         }
178
179         if (!_osc_server) {
180                 return 1;
181         }
182         
183 #ifdef ARDOUR_OSC_UNIX_SERVER
184         
185         // APPEARS sluggish for now
186         
187         // attempt to create unix socket server too
188         
189         snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
190         int fd = mkstemp(tmpstr);
191         
192         if (fd >= 0 ) {
193                 ::g_unlink (tmpstr);
194                 close (fd);
195                 
196                 _osc_unix_server = lo_server_new (tmpstr, error_callback);
197                 
198                 if (_osc_unix_server) {
199                         _osc_unix_socket_path = tmpstr;
200                 }
201         }
202 #endif
203         
204         PBD::info << "OSC @ " << get_server_url () << endmsg;
205
206         std::string url_file;
207
208         if (find_file_in_search_path (ardour_config_search_path(), "osc_url", url_file)) {
209                 
210                 _osc_url_file = url_file;
211                 ofstream urlfile;
212                 urlfile.open(_osc_url_file.c_str(), ios::trunc);
213                 
214                 if (urlfile) {
215                         urlfile << get_server_url () << endl;
216                         urlfile.close();
217                 } else {  
218                         cerr << "Couldn't write '" <<  _osc_url_file << "'" <<endl;
219                 }
220         }
221         
222         register_callbacks();
223         
224         // lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
225
226         /* startup the event loop thread */
227
228         BaseUI::run ();
229
230         return 0;
231 }
232
233 void
234 OSC::thread_init ()
235 {
236         pthread_set_name (X_("OSC"));
237
238         if (_osc_unix_server) {
239                 Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
240                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_unix_server));
241                 src->attach (_main_loop->get_context());
242                 local_server = src->gobj();
243                 g_source_ref (local_server);
244         }
245
246         if (_osc_server) {
247                 Glib::RefPtr<IOSource> src  = IOSource::create (lo_server_get_socket_fd (_osc_server), IO_IN|IO_HUP|IO_ERR);
248                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_server));
249                 src->attach (_main_loop->get_context());
250                 remote_server = src->gobj();
251                 g_source_ref (remote_server);
252         }
253
254         PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("OSC"), 2048);
255         SessionEvent::create_per_thread_pool (X_("OSC"), 128);
256 }
257
258 int
259 OSC::stop ()
260 {
261         /* stop main loop */
262
263         if (local_server) {
264                 g_source_destroy (local_server);
265                 g_source_unref (local_server);
266                 local_server = 0;
267         }
268
269         if (remote_server) {
270                 g_source_destroy (remote_server);
271                 g_source_unref (remote_server);
272                 remote_server = 0;
273         }
274
275         BaseUI::quit ();
276
277         if (_osc_server) {
278                 int fd = lo_server_get_socket_fd(_osc_server);
279                 if (fd >=0) {
280                         close(fd);
281                 }
282                 lo_server_free (_osc_server);
283                 _osc_server = 0;
284         }
285
286         if (_osc_unix_server) {
287                 int fd = lo_server_get_socket_fd(_osc_unix_server);
288                 if (fd >=0) {
289                         close(fd);
290                 }
291                 lo_server_free (_osc_unix_server);
292                 _osc_unix_server = 0;
293         }
294         
295         if (!_osc_unix_socket_path.empty()) {
296                 ::g_unlink (_osc_unix_socket_path.c_str());
297         }
298         
299         if (!_osc_url_file.empty() ) {
300                 ::g_unlink (_osc_url_file.c_str() );
301         }
302
303         // Delete any active route observers
304         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
305
306                 OSCRouteObserver* rc;
307                 
308                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
309                         delete *x;
310                         x = route_observers.erase (x);
311                 } else {
312                         ++x;
313                 }
314         }
315         
316         return 0;
317 }
318
319 void
320 OSC::register_callbacks()
321 {
322         lo_server srvs[2];
323         lo_server serv;
324
325         srvs[0] = _osc_server;
326         srvs[1] = _osc_unix_server;
327         
328         for (size_t i = 0; i < 2; ++i) {
329
330                 if (!srvs[i]) {
331                         continue;
332                 }
333
334                 serv = srvs[i];
335                 
336                 /* this is a special catchall handler */
337                 
338                 lo_server_add_method (serv, 0, 0, _catchall, this);
339                 
340 #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this)
341                 
342                 REGISTER_CALLBACK (serv, "/routes/list", "", routes_list);
343                 REGISTER_CALLBACK (serv, "/ardour/add_marker", "", add_marker);
344                 REGISTER_CALLBACK (serv, "/ardour/access_action", "s", access_action);
345                 REGISTER_CALLBACK (serv, "/ardour/loop_toggle", "", loop_toggle);
346                 REGISTER_CALLBACK (serv, "/ardour/goto_start", "", goto_start);
347                 REGISTER_CALLBACK (serv, "/ardour/goto_end", "", goto_end);
348                 REGISTER_CALLBACK (serv, "/ardour/rewind", "", rewind);
349                 REGISTER_CALLBACK (serv, "/ardour/ffwd", "", ffwd);
350                 REGISTER_CALLBACK (serv, "/ardour/transport_stop", "", transport_stop);
351                 REGISTER_CALLBACK (serv, "/ardour/transport_play", "", transport_play);
352                 REGISTER_CALLBACK (serv, "/ardour/transport_frame", "", transport_frame);
353                 REGISTER_CALLBACK (serv, "/ardour/set_transport_speed", "f", set_transport_speed);
354                 REGISTER_CALLBACK (serv, "/ardour/locate", "ii", locate);
355                 REGISTER_CALLBACK (serv, "/ardour/save_state", "", save_state);
356                 REGISTER_CALLBACK (serv, "/ardour/prev_marker", "", prev_marker);
357                 REGISTER_CALLBACK (serv, "/ardour/next_marker", "", next_marker);
358                 REGISTER_CALLBACK (serv, "/ardour/undo", "", undo);
359                 REGISTER_CALLBACK (serv, "/ardour/redo", "", redo);
360                 REGISTER_CALLBACK (serv, "/ardour/toggle_punch_in", "", toggle_punch_in);
361                 REGISTER_CALLBACK (serv, "/ardour/toggle_punch_out", "", toggle_punch_out);
362                 REGISTER_CALLBACK (serv, "/ardour/rec_enable_toggle", "", rec_enable_toggle);
363                 REGISTER_CALLBACK (serv, "/ardour/toggle_all_rec_enables", "", toggle_all_rec_enables);
364
365                 REGISTER_CALLBACK (serv, "/ardour/routes/mute", "ii", route_mute);
366                 REGISTER_CALLBACK (serv, "/ardour/routes/solo", "ii", route_solo);
367                 REGISTER_CALLBACK (serv, "/ardour/routes/recenable", "ii", route_recenable);
368                 REGISTER_CALLBACK (serv, "/ardour/routes/gainabs", "if", route_set_gain_abs);
369                 REGISTER_CALLBACK (serv, "/ardour/routes/gaindB", "if", route_set_gain_dB);
370                 REGISTER_CALLBACK (serv, "/ardour/routes/pan_stereo_position", "if", route_set_pan_stereo_position);
371                 REGISTER_CALLBACK (serv, "/ardour/routes/pan_stereo_width", "if", route_set_pan_stereo_width);
372                 REGISTER_CALLBACK (serv, "/ardour/routes/plugin/parameter", "iiif", route_plugin_parameter);
373                 REGISTER_CALLBACK (serv, "/ardour/routes/plugin/parameter/print", "iii", route_plugin_parameter_print);
374                 REGISTER_CALLBACK (serv, "/ardour/routes/send/gainabs", "iif", route_set_send_gain_abs);
375                 REGISTER_CALLBACK (serv, "/ardour/routes/send/gaindB", "iif", route_set_send_gain_dB);
376
377                 /* still not-really-standardized query interface */
378                 //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
379                 //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
380
381                 // un/register_update args= s:ctrl s:returl s:retpath
382                 //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
383                 //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
384                 //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
385                 //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
386
387         }
388 }
389
390 bool
391 OSC::osc_input_handler (IOCondition ioc, lo_server srv)
392 {
393         if (ioc & ~IO_IN) {
394                 return false;
395         }
396
397         if (ioc & IO_IN) {
398                 lo_server_recv (srv);
399         }
400
401         return true;
402 }
403
404 std::string
405 OSC::get_server_url()
406 {
407         string url;
408         char * urlstr;
409
410         if (_osc_server) {
411                 urlstr = lo_server_get_url (_osc_server);
412                 url = urlstr;
413                 free (urlstr);
414         }
415         
416         return url;
417 }
418
419 std::string
420 OSC::get_unix_server_url()
421 {
422         string url;
423         char * urlstr;
424
425         if (_osc_unix_server) {
426                 urlstr = lo_server_get_url (_osc_unix_server);
427                 url = urlstr;
428                 free (urlstr);
429         }
430         
431         return url;
432 }
433
434 void
435 OSC::listen_to_route (boost::shared_ptr<Route> route, lo_address addr)
436 {
437         /* avoid duplicate listens */
438         
439         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); ++x) {
440                 
441                 OSCRouteObserver* ro;
442
443                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
444
445                         int res = strcmp(lo_address_get_hostname(ro->address()), lo_address_get_hostname(addr));
446                         
447                         if (ro->route() == route && res == 0) {
448                                 return;
449                         }
450                 }
451         }
452
453         OSCRouteObserver* o = new OSCRouteObserver (route, addr);
454         route_observers.push_back (o);
455
456         route->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr<Route> (route)), this);
457 }
458
459 void
460 OSC::drop_route (boost::weak_ptr<Route> wr)
461 {
462         boost::shared_ptr<Route> r = wr.lock ();
463
464         if (!r) {
465                 return;
466         }
467
468         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
469
470                 OSCRouteObserver* rc;
471                 
472                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
473                   
474                         if (rc->route() == r) {
475                                 delete *x;
476                                 x = route_observers.erase (x);
477                         } else {
478                                 ++x;
479                         }
480                 } else {
481                         ++x;
482                 }
483         }
484 }
485
486 void
487 OSC::end_listen (boost::shared_ptr<Route> r, lo_address addr)
488 {
489         RouteObservers::iterator x;
490         
491         // Remove the route observers
492         for (x = route_observers.begin(); x != route_observers.end();) {
493
494                 OSCRouteObserver* ro;
495                 
496                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
497                   
498                         int res = strcmp(lo_address_get_hostname(ro->address()), lo_address_get_hostname(addr));
499
500                         if (ro->route() == r && res == 0) {
501                                 delete *x;
502                                 x = route_observers.erase (x);
503                         }
504                         else {
505                                 ++x;
506                         }
507                 }
508                 else {
509                         ++x;
510                 }
511         }
512 }
513
514 void
515 OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg)
516 {
517         char* subpath;
518         
519         subpath = (char*) malloc (len-15+1);
520         memcpy (subpath, path, len-15);
521         subpath[len-15] = '\0';
522         
523         send_current_value (subpath, argv, argc, msg);
524         
525         free (subpath);
526 }
527
528 void
529 OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg)
530 {
531         if (!session) {
532                 return;
533         }
534
535         lo_message reply = lo_message_new ();
536         boost::shared_ptr<Route> r;
537         int id;
538
539         lo_message_add_string (reply, path);
540         
541         if (argc == 0) {
542                 lo_message_add_string (reply, "bad syntax");
543         } else {
544                 id = argv[0]->i;
545                 r = session->route_by_remote_id (id);
546
547                 if (!r) {
548                         lo_message_add_string (reply, "not found");
549                 } else {
550
551                         if (strcmp (path, "/routes/state") == 0) {
552                                 
553                                 if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
554                                         lo_message_add_string (reply, "AT");
555                                 } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
556                                         lo_message_add_string (reply, "MT");
557                                 } else {
558                                         lo_message_add_string (reply, "B");
559                                 }
560                                 
561                                 lo_message_add_string (reply, r->name().c_str());
562                                 lo_message_add_int32 (reply, r->n_inputs().n_audio());
563                                 lo_message_add_int32 (reply, r->n_outputs().n_audio());
564                                 lo_message_add_int32 (reply, r->muted());
565                                 lo_message_add_int32 (reply, r->soloed());
566                                 
567                         } else if (strcmp (path, "/routes/mute") == 0) {
568                                 
569                                 lo_message_add_int32 (reply, (float) r->muted());
570                                 
571                         } else if (strcmp (path, "/routes/solo") == 0) {
572                                 
573                                 lo_message_add_int32 (reply, r->soloed());
574                         }
575                 }
576         }
577
578         lo_send_message (lo_message_get_source (msg), "#reply", reply);
579         lo_message_free (reply);
580 }
581         
582 int
583 OSC::_catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) 
584 {
585         return ((OSC*)user_data)->catchall (path, types, argv, argc, data);
586 }
587
588 int
589 OSC::catchall (const char *path, const char* /*types*/, lo_arg **argv, int argc, lo_message msg) 
590 {
591         size_t len;
592         int ret = 1; /* unhandled */
593
594         //cerr << "Received a message, path = " << path << " types = \"" 
595         //     << (types ? types : "NULL") << '"' << endl;
596
597         /* 15 for /#current_value plus 2 for /<path> */
598
599         len = strlen (path);
600
601         if (len >= 17 && !strcmp (&path[len-15], "/#current_value")) {
602                 current_value_query (path, len, argv, argc, msg);
603                 ret = 0;
604
605         } else if (strcmp (path, "/routes/listen") == 0) {
606                 
607                 cerr << "set up listener\n";
608
609                 lo_message reply = lo_message_new ();
610
611                 if (argc <= 0) {
612                         lo_message_add_string (reply, "syntax error");
613                 } else {
614                         for (int n = 0; n < argc; ++n) {
615
616                                 boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
617                                 
618                                 if (!r) {
619                                         lo_message_add_string (reply, "not found");
620                                         cerr << "no such route\n";
621                                         break;
622                                 } else {                        
623                                         cerr << "add listener\n";
624                                         listen_to_route (r, lo_message_get_source (msg));
625                                         lo_message_add_int32 (reply, argv[n]->i);
626                                 }
627                         }
628                 }
629
630                 lo_send_message (lo_message_get_source (msg), "#reply", reply);
631                 lo_message_free (reply);
632                 
633                 ret = 0;
634
635         } else if (strcmp (path, "/routes/ignore") == 0) {
636
637                 for (int n = 0; n < argc; ++n) {
638
639                         boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
640                         
641                         if (r) {
642                                 end_listen (r, lo_message_get_source (msg));
643                         }
644                 }
645                 
646                 ret = 0;        
647         } 
648
649         return ret;
650 }
651
652 void
653 OSC::update_clock ()
654 {
655   
656 }
657
658 // "Application Hook" Handlers //
659 void
660 OSC::session_loaded (Session& s)
661 {
662         lo_address listener = lo_address_new (NULL, "7770");
663         lo_send (listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str());
664 }
665
666 void
667 OSC::session_exported (std::string path, std::string name)
668 {
669         lo_address listener = lo_address_new (NULL, "7770");
670         lo_send (listener, "/session/exported", "ss", path.c_str(), name.c_str());
671 }
672
673 // end "Application Hook" Handlers //
674
675 /* path callbacks */
676
677 int 
678 OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, void */*data*/, void* /*user_data*/) 
679
680 #if 0
681         const char* returl;
682
683         if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != s) {
684                 return 1;
685         }
686
687         const char *returl = argv[1]->s;
688         lo_address addr = find_or_cache_addr (returl);
689
690         const char *retpath = argv[2]->s;
691
692         
693         if (strcmp (argv[0]->s, "transport_frame") == 0) {
694
695                 if (session) {
696                         lo_send (addr, retpath, "i", session->transport_frame());
697                 }
698
699         } else if (strcmp (argv[0]->s, "transport_speed") == 0) {
700                 
701                 if (session) {
702                         lo_send (addr, retpath, "i", session->transport_frame());
703                 }
704                 
705         } else if (strcmp (argv[0]->s, "transport_locked") == 0) {
706                 
707                 if (session) {
708                         lo_send (addr, retpath, "i", session->transport_frame());
709                 }
710                 
711         } else if (strcmp (argv[0]->s, "punch_in") == 0) {
712                 
713                 if (session) {
714                         lo_send (addr, retpath, "i", session->transport_frame());
715                 }
716                 
717         } else if (strcmp (argv[0]->s, "punch_out") == 0) {
718
719                 if (session) {
720                         lo_send (addr, retpath, "i", session->transport_frame());
721                 }
722                 
723         } else if (strcmp (argv[0]->s, "rec_enable") == 0) {
724                         
725                 if (session) {
726                         lo_send (addr, retpath, "i", session->transport_frame());
727                 }
728
729         } else {
730
731                 /* error */
732         }
733 #endif
734         return 0;
735 }
736
737 void
738 OSC::routes_list (lo_message msg)
739 {
740         for (int n = 0; n < (int) session->nroutes(); ++n) {
741
742                 boost::shared_ptr<Route> r = session->route_by_remote_id (n);
743                 
744                 if (r) {
745
746                         lo_message reply = lo_message_new ();
747                 
748                         if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
749                                 lo_message_add_string (reply, "AT");
750                         } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
751                                 lo_message_add_string (reply, "MT");
752                         } else {
753                                 lo_message_add_string (reply, "B");
754                         }
755                         
756                         lo_message_add_string (reply, r->name().c_str());
757                         lo_message_add_int32 (reply, r->n_inputs().n_audio());
758                         lo_message_add_int32 (reply, r->n_outputs().n_audio());
759                         lo_message_add_int32 (reply, r->muted());
760                         lo_message_add_int32 (reply, r->soloed());
761                         lo_message_add_int32 (reply, r->remote_control_id());
762                         
763                         if (boost::dynamic_pointer_cast<AudioTrack>(r) 
764                                 || boost::dynamic_pointer_cast<MidiTrack>(r)) {
765         
766                                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
767                                 lo_message_add_int32 (reply, t->record_enabled());
768                         }
769
770                         //Automatically listen to routes listed
771                         listen_to_route(r, lo_message_get_source (msg));
772
773                         lo_send_message (lo_message_get_source (msg), "#reply", reply);
774                         lo_message_free (reply);
775                 }
776         }
777         
778         // Send end of listing message
779         lo_message reply = lo_message_new ();
780
781         lo_message_add_string (reply, "end_route_list");
782         lo_message_add_int64 (reply, session->frame_rate());
783         lo_message_add_int64 (reply, session->current_end_frame());
784         
785         lo_send_message (lo_message_get_source (msg), "#reply", reply);
786         
787         lo_message_free (reply);
788 }
789
790 void
791 OSC::transport_frame (lo_message msg)
792 {
793                 framepos_t pos = session->transport_frame ();
794                 
795                 lo_message reply = lo_message_new ();
796                 lo_message_add_int64 (reply, pos);
797                 
798                 lo_send_message (lo_message_get_source (msg), "/ardour/transport_frame", reply);
799                 
800                 lo_message_free (reply);
801 }
802
803 int
804 OSC::route_mute (int rid, int yn)
805 {
806         if (!session) return -1;
807
808         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
809
810         if (r) {
811                 r->set_mute (yn, this);
812         }
813         
814         return 0;
815 }
816
817 int
818 OSC::route_solo (int rid, int yn)
819 {
820         if (!session) return -1;
821
822         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
823
824         if (r) {
825                 r->set_solo (yn, this);
826         }
827         
828         return 0;
829 }
830
831 int
832 OSC::route_recenable (int rid, int yn)
833 {
834         if (!session) return -1;
835
836         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
837
838         if (r) {
839                 r->set_record_enabled (yn, this);
840         }
841         
842         return 0;
843 }
844
845 int
846 OSC::route_set_gain_abs (int rid, float level)
847 {
848         if (!session) return -1;
849
850         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
851
852         if (r) {
853                 r->set_gain (level, this);
854         }
855
856         return 0;
857 }
858
859 int
860 OSC::route_set_gain_dB (int rid, float dB)
861 {
862         if (!session) return -1;
863
864         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
865
866         if (r) {
867                 r->set_gain (dB_to_coefficient (dB), this);
868         }
869         
870         return 0;
871 }
872
873 int
874 OSC::route_set_pan_stereo_position (int rid, float pos)
875 {
876         if (!session) return -1;
877
878         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
879
880         if (r) {
881                 boost::shared_ptr<Panner> panner = r->panner();
882                 if (panner) {
883                         panner->set_position (pos);
884                 }
885         }
886         
887         return 0;
888
889 }
890
891 int
892 OSC::route_set_pan_stereo_width (int rid, float pos)
893 {
894         if (!session) return -1;
895
896         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
897
898         if (r) {
899                 boost::shared_ptr<Panner> panner = r->panner();
900                 if (panner) {
901                         panner->set_width (pos);
902                 }
903         }
904         
905         return 0;
906
907 }
908
909 int
910 OSC::route_set_send_gain_abs (int rid, int sid, float val)
911 {
912         if (!session) { 
913                 return -1;
914         }
915
916         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);  
917
918         if (!r) {
919                 return -1;
920         }
921
922         /* revert to zero-based counting */
923
924         if (sid > 0) {
925                 --sid;
926         }
927
928         boost::shared_ptr<Processor> p = r->nth_send (sid);
929         
930         if (p) {
931                 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
932                 boost::shared_ptr<Amp> a = s->amp();
933                 
934                 if (a) {
935                         a->set_gain (val, this);
936                 }
937         }
938         return 0;
939 }
940
941 int
942 OSC::route_set_send_gain_dB (int rid, int sid, float val)
943 {
944         if (!session) { 
945                 return -1;
946         }
947
948         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);  
949
950         if (!r) {
951                 return -1;
952         }
953
954         /* revert to zero-based counting */
955
956         if (sid > 0) {
957                 --sid;
958         }
959
960         boost::shared_ptr<Processor> p = r->nth_send (sid);
961         
962         if (p) {
963                 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
964                 boost::shared_ptr<Amp> a = s->amp();
965                 
966                 if (a) {
967                         a->set_gain (dB_to_coefficient (val), this);
968                 }
969         }
970         return 0;
971 }
972
973 int
974 OSC::route_plugin_parameter (int rid, int piid, int par, float val)
975 {
976         if (!session) { 
977                 return -1;
978         }
979
980         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);  
981
982         if (!r) {
983                 return -1;
984         }
985
986         boost::shared_ptr<Processor> redi=r->nth_processor (piid);
987         
988         if (!redi) {
989                 return -1;
990         }
991
992         boost::shared_ptr<PluginInsert> pi;
993         
994         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
995                 return -1;
996         }
997
998         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
999         bool ok=false;
1000         
1001         uint32_t controlid = pip->nth_parameter (par,ok);
1002         
1003         if (!ok) {
1004                 return -1;
1005         }
1006
1007         Plugin::ParameterDescriptor pd;
1008         pi->plugin()->get_parameter_descriptor (controlid,pd);
1009
1010         if (val >= pd.lower && val < pd.upper) {
1011                 
1012                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));;
1013                 cerr << "parameter:" << redi->describe_parameter(controlid) << " val:" << val << "\n";
1014                 c->set_value (val);
1015         }  
1016
1017         return 0;
1018 }
1019
1020 int
1021 OSC::route_plugin_parameter_print (int rid, int piid, int par)
1022 {
1023         if (!session) { 
1024                 return -1;
1025         }
1026
1027         boost::shared_ptr<Route> r = session->route_by_remote_id (rid);  
1028
1029         if (!r) {
1030                 return -1;
1031         }
1032
1033         boost::shared_ptr<Processor> redi=r->nth_processor (piid);
1034         
1035         if (!redi) {
1036                 return -1;
1037         }
1038
1039         boost::shared_ptr<PluginInsert> pi;
1040         
1041         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
1042                 return -1;
1043         }
1044         
1045         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
1046         bool ok=false;
1047         
1048         uint32_t controlid = pip->nth_parameter (par,ok);
1049         
1050         if (!ok) {
1051                 return -1;
1052         }
1053
1054         Plugin::ParameterDescriptor pd;
1055
1056         if (pi->plugin()->get_parameter_descriptor (controlid, pd) == 0) {
1057                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
1058                 
1059                 cerr << "parameter:     " << redi->describe_parameter(controlid)  << "\n";
1060                 cerr << "current value: " << c->get_value ();
1061                 cerr << "lower value:   " << pd.lower << "\n";
1062                 cerr << "upper value:   " << pd.upper << "\n";
1063         }
1064
1065         return 0;
1066 }
1067
1068 XMLNode& 
1069 OSC::get_state () 
1070 {
1071         XMLNode& node (ControlProtocol::get_state());
1072
1073         node.add_property (X_("feedback"), _send_route_changes ? "1" : "0");
1074         return node;
1075 }
1076
1077 int 
1078 OSC::set_state (const XMLNode& node, int /*version*/)
1079 {
1080         const XMLProperty* prop = node.property (X_("feedback"));
1081
1082         if (prop) {
1083                 if (PBD::string_is_affirmative (prop->value())) {
1084                         _send_route_changes = true;
1085                 } else {
1086                         _send_route_changes = false;
1087                 }
1088         } else {
1089                 /* leave it alone */
1090         }
1091               
1092         return 0;
1093 }