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