6a5d4d3cd1747903bdea92cc2f153a1a4c2c25da
[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 <cstdio>
21 #include <cstdlib>
22 #include <cerrno>
23 #include <algorithm>
24
25 #include <unistd.h>
26 #include <fcntl.h>
27
28 #include "pbd/gstdio_compat.h"
29 #include <glibmm/miscutils.h>
30
31 #include <pbd/convert.h>
32 #include <pbd/pthread_utils.h>
33 #include <pbd/file_utils.h>
34 #include <pbd/failed_constructor.h>
35
36 #include "ardour/amp.h"
37 #include "ardour/session.h"
38 #include "ardour/route.h"
39 #include "ardour/audio_track.h"
40 #include "ardour/midi_track.h"
41 #include "ardour/monitor_control.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/plugin_insert.h"
47 #include "ardour/presentation_info.h"
48 #include "ardour/send.h"
49
50 #include "osc_select_observer.h"
51 #include "osc.h"
52 #include "osc_controllable.h"
53 #include "osc_route_observer.h"
54 #include "osc_global_observer.h"
55 #include "i18n.h"
56
57 using namespace ARDOUR;
58 using namespace std;
59 using namespace Glib;
60 using namespace ArdourSurface;
61
62 #include "pbd/abstract_ui.cc" // instantiate template
63
64 OSC* OSC::_instance = 0;
65
66 #ifdef DEBUG
67 static void error_callback(int num, const char *m, const char *path)
68 {
69         fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
70 }
71 #else
72 static void error_callback(int, const char *, const char *)
73 {
74
75 }
76 #endif
77
78 OSC::OSC (Session& s, uint32_t port)
79         : ControlProtocol (s, X_("Open Sound Control (OSC)"))
80         , AbstractUI<OSCUIRequest> (name())
81         , local_server (0)
82         , remote_server (0)
83         , _port(port)
84         , _ok (true)
85         , _shutdown (false)
86         , _osc_server (0)
87         , _osc_unix_server (0)
88         , _send_route_changes (true)
89         , _debugmode (Off)
90         , gui (0)
91 {
92         _instance = this;
93
94         session->Exported.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::session_exported, this, _1, _2), this);
95 }
96
97 OSC::~OSC()
98 {
99         stop ();
100         _instance = 0;
101 }
102
103 void*
104 OSC::request_factory (uint32_t num_requests)
105 {
106         /* AbstractUI<T>::request_buffer_factory() is a template method only
107            instantiated in this source module. To provide something visible for
108            use in the interface/descriptor, we have this static method that is
109            template-free.
110         */
111         return request_buffer_factory (num_requests);
112 }
113
114 void
115 OSC::do_request (OSCUIRequest* req)
116 {
117         if (req->type == CallSlot) {
118
119                 call_slot (MISSING_INVALIDATOR, req->the_slot);
120
121         } else if (req->type == Quit) {
122
123                 stop ();
124         }
125 }
126
127 int
128 OSC::set_active (bool yn)
129 {
130         if (yn != active()) {
131
132                 if (yn) {
133                         if (start ()) {
134                                 return -1;
135                         }
136                 } else {
137                         if (stop ()) {
138                                 return -1;
139                         }
140                 }
141
142         }
143
144         return ControlProtocol::set_active (yn);
145 }
146
147 bool
148 OSC::get_active () const
149 {
150         return _osc_server != 0;
151 }
152
153 int
154 OSC::set_feedback (bool yn)
155 {
156         _send_route_changes = yn;
157         return 0;
158 }
159
160 bool
161 OSC::get_feedback () const
162 {
163         return _send_route_changes;
164 }
165
166 int
167 OSC::start ()
168 {
169         char tmpstr[255];
170
171         if (_osc_server) {
172                 /* already started */
173                 return 0;
174         }
175
176         for (int j=0; j < 20; ++j) {
177                 snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
178
179                 //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
180                 //      break;
181                 //}
182
183                 if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
184                         break;
185                 }
186
187 #ifdef DEBUG
188                 cerr << "can't get osc at port: " << _port << endl;
189 #endif
190                 _port++;
191                 continue;
192         }
193
194         if (!_osc_server) {
195                 return 1;
196         }
197
198 #ifdef ARDOUR_OSC_UNIX_SERVER
199
200         // APPEARS sluggish for now
201
202         // attempt to create unix socket server too
203
204         snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
205         int fd = mkstemp(tmpstr);
206
207         if (fd >= 0 ) {
208                 ::g_unlink (tmpstr);
209                 close (fd);
210
211                 _osc_unix_server = lo_server_new (tmpstr, error_callback);
212
213                 if (_osc_unix_server) {
214                         _osc_unix_socket_path = tmpstr;
215                 }
216         }
217 #endif
218
219         PBD::info << "OSC @ " << get_server_url () << endmsg;
220
221         std::string url_file;
222
223         if (find_file (ardour_config_search_path(), "osc_url", url_file)) {
224                 _osc_url_file = url_file;
225                 if (g_file_set_contents (_osc_url_file.c_str(), get_server_url().c_str(), -1, NULL)) {
226                         cerr << "Couldn't write '" <<  _osc_url_file << "'" <<endl;
227                 }
228         }
229
230         register_callbacks();
231
232         session_loaded (*session);
233
234         // lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
235
236         /* startup the event loop thread */
237
238         BaseUI::run ();
239
240         // start timers for metering, timecode and heartbeat.
241         // timecode and metering run at 100
242         Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
243         periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &OSC::periodic));
244         periodic_timeout->attach (main_loop()->get_context());
245
246         //StripableSelectionChanged.connect (gui_connections, MISSING_INVALIDATOR, boost::bind (&OSC::gui_selection_changed, this, _1), this);
247
248         return 0;
249 }
250
251 void
252 OSC::thread_init ()
253 {
254         pthread_set_name (event_loop_name().c_str());
255
256         if (_osc_unix_server) {
257                 Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
258                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_unix_server));
259                 src->attach (_main_loop->get_context());
260                 local_server = src->gobj();
261                 g_source_ref (local_server);
262         }
263
264         if (_osc_server) {
265 #ifdef PLATFORM_WINDOWS
266                 Glib::RefPtr<IOChannel> chan = Glib::IOChannel::create_from_win32_socket (lo_server_get_socket_fd (_osc_server));
267                 Glib::RefPtr<IOSource> src  = IOSource::create (chan, IO_IN|IO_HUP|IO_ERR);
268 #else
269                 Glib::RefPtr<IOSource> src  = IOSource::create (lo_server_get_socket_fd (_osc_server), IO_IN|IO_HUP|IO_ERR);
270 #endif
271                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_server));
272                 src->attach (_main_loop->get_context());
273                 remote_server = src->gobj();
274                 g_source_ref (remote_server);
275         }
276
277         PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
278         SessionEvent::create_per_thread_pool (event_loop_name(), 128);
279 }
280
281 int
282 OSC::stop ()
283 {
284         /* stop main loop */
285
286         if (local_server) {
287                 g_source_destroy (local_server);
288                 g_source_unref (local_server);
289                 local_server = 0;
290         }
291
292         if (remote_server) {
293                 g_source_destroy (remote_server);
294                 g_source_unref (remote_server);
295                 remote_server = 0;
296         }
297
298         BaseUI::quit ();
299
300         if (_osc_server) {
301                 lo_server_free (_osc_server);
302                 _osc_server = 0;
303         }
304
305         if (_osc_unix_server) {
306                 lo_server_free (_osc_unix_server);
307                 _osc_unix_server = 0;
308         }
309
310         if (!_osc_unix_socket_path.empty()) {
311                 ::g_unlink (_osc_unix_socket_path.c_str());
312         }
313
314         if (!_osc_url_file.empty() ) {
315                 ::g_unlink (_osc_url_file.c_str() );
316         }
317
318         periodic_connection.disconnect ();
319         // Delete any active route observers
320         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
321
322                 OSCRouteObserver* rc;
323
324                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
325                         delete *x;
326                         x = route_observers.erase (x);
327                 } else {
328                         ++x;
329                 }
330         }
331 // Should maybe do global_observers too
332         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end();) {
333
334                 OSCGlobalObserver* gc;
335
336                 if ((gc = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
337                         delete *x;
338                         x = global_observers.erase (x);
339                 } else {
340                         ++x;
341                 }
342         }
343 // delete select observers
344         for (uint32_t it = 0; it < _surface.size(); ++it) {
345                 OSCSurface* sur = &_surface[it];
346                 OSCSelectObserver* so;
347                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
348                         delete so;
349                 }
350         }
351
352         return 0;
353 }
354
355 void
356 OSC::register_callbacks()
357 {
358         lo_server srvs[2];
359         lo_server serv;
360
361         srvs[0] = _osc_server;
362         srvs[1] = _osc_unix_server;
363
364         for (size_t i = 0; i < 2; ++i) {
365
366                 if (!srvs[i]) {
367                         continue;
368                 }
369
370                 serv = srvs[i];
371
372
373 #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this)
374
375                 // Some controls have optional "f" for feedback or touchosc
376                 // http://hexler.net/docs/touchosc-controls-reference
377
378                 REGISTER_CALLBACK (serv, "/set_surface", "iiii", set_surface);
379                 REGISTER_CALLBACK (serv, "/set_surface/feedback", "i", set_surface_feedback);
380                 REGISTER_CALLBACK (serv, "/set_surface/bank_size", "i", set_surface_bank_size);
381                 REGISTER_CALLBACK (serv, "/set_surface/gainmode", "i", set_surface_gainmode);
382                 REGISTER_CALLBACK (serv, "/set_surface/strip_types", "i", set_surface_strip_types);
383                 REGISTER_CALLBACK (serv, "/strip/list", "", routes_list);
384                 REGISTER_CALLBACK (serv, "/add_marker", "", add_marker);
385                 REGISTER_CALLBACK (serv, "/add_marker", "f", add_marker);
386                 REGISTER_CALLBACK (serv, "/access_action", "s", access_action);
387                 REGISTER_CALLBACK (serv, "/loop_toggle", "", loop_toggle);
388                 REGISTER_CALLBACK (serv, "/loop_toggle", "f", loop_toggle);
389                 REGISTER_CALLBACK (serv, "/loop_location", "ii", loop_location);
390                 REGISTER_CALLBACK (serv, "/goto_start", "", goto_start);
391                 REGISTER_CALLBACK (serv, "/goto_start", "f", goto_start);
392                 REGISTER_CALLBACK (serv, "/goto_end", "", goto_end);
393                 REGISTER_CALLBACK (serv, "/goto_end", "f", goto_end);
394                 REGISTER_CALLBACK (serv, "/rewind", "", rewind);
395                 REGISTER_CALLBACK (serv, "/rewind", "f", rewind);
396                 REGISTER_CALLBACK (serv, "/ffwd", "", ffwd);
397                 REGISTER_CALLBACK (serv, "/ffwd", "f", ffwd);
398                 REGISTER_CALLBACK (serv, "/transport_stop", "", transport_stop);
399                 REGISTER_CALLBACK (serv, "/transport_stop", "f", transport_stop);
400                 REGISTER_CALLBACK (serv, "/transport_play", "", transport_play);
401                 REGISTER_CALLBACK (serv, "/transport_play", "f", transport_play);
402                 REGISTER_CALLBACK (serv, "/transport_frame", "", transport_frame);
403                 REGISTER_CALLBACK (serv, "/transport_speed", "", transport_speed);
404                 REGISTER_CALLBACK (serv, "/record_enabled", "", record_enabled);
405                 REGISTER_CALLBACK (serv, "/set_transport_speed", "f", set_transport_speed);
406                 // locate ii is position and bool roll
407                 REGISTER_CALLBACK (serv, "/locate", "ii", locate);
408                 REGISTER_CALLBACK (serv, "/save_state", "", save_state);
409                 REGISTER_CALLBACK (serv, "/save_state", "f", save_state);
410                 REGISTER_CALLBACK (serv, "/prev_marker", "", prev_marker);
411                 REGISTER_CALLBACK (serv, "/prev_marker", "f", prev_marker);
412                 REGISTER_CALLBACK (serv, "/next_marker", "", next_marker);
413                 REGISTER_CALLBACK (serv, "/next_marker", "f", next_marker);
414                 REGISTER_CALLBACK (serv, "/undo", "", undo);
415                 REGISTER_CALLBACK (serv, "/undo", "f", undo);
416                 REGISTER_CALLBACK (serv, "/redo", "", redo);
417                 REGISTER_CALLBACK (serv, "/redo", "f", redo);
418                 REGISTER_CALLBACK (serv, "/toggle_punch_in", "", toggle_punch_in);
419                 REGISTER_CALLBACK (serv, "/toggle_punch_in", "f", toggle_punch_in);
420                 REGISTER_CALLBACK (serv, "/toggle_punch_out", "", toggle_punch_out);
421                 REGISTER_CALLBACK (serv, "/toggle_punch_out", "f", toggle_punch_out);
422                 REGISTER_CALLBACK (serv, "/rec_enable_toggle", "", rec_enable_toggle);
423                 REGISTER_CALLBACK (serv, "/rec_enable_toggle", "f", rec_enable_toggle);
424                 REGISTER_CALLBACK (serv, "/toggle_all_rec_enables", "", toggle_all_rec_enables);
425                 REGISTER_CALLBACK (serv, "/toggle_all_rec_enables", "f", toggle_all_rec_enables);
426                 REGISTER_CALLBACK (serv, "/all_tracks_rec_in", "f", all_tracks_rec_in);
427                 REGISTER_CALLBACK (serv, "/all_tracks_rec_out", "f", all_tracks_rec_out);
428                 REGISTER_CALLBACK (serv, "/remove_marker", "", remove_marker_at_playhead);
429                 REGISTER_CALLBACK (serv, "/remove_marker", "f", remove_marker_at_playhead);
430                 REGISTER_CALLBACK (serv, "/jump_bars", "f", jump_by_bars);
431                 REGISTER_CALLBACK (serv, "/jump_seconds", "f", jump_by_seconds);
432                 REGISTER_CALLBACK (serv, "/mark_in", "", mark_in);
433                 REGISTER_CALLBACK (serv, "/mark_in", "f", mark_in);
434                 REGISTER_CALLBACK (serv, "/mark_out", "", mark_out);
435                 REGISTER_CALLBACK (serv, "/mark_out", "f", mark_out);
436                 REGISTER_CALLBACK (serv, "/toggle_click", "", toggle_click);
437                 REGISTER_CALLBACK (serv, "/toggle_click", "f", toggle_click);
438                 REGISTER_CALLBACK (serv, "/midi_panic", "", midi_panic);
439                 REGISTER_CALLBACK (serv, "/midi_panic", "f", midi_panic);
440                 REGISTER_CALLBACK (serv, "/toggle_roll", "", toggle_roll);
441                 REGISTER_CALLBACK (serv, "/toggle_roll", "f", toggle_roll);
442                 REGISTER_CALLBACK (serv, "/stop_forget", "", stop_forget);
443                 REGISTER_CALLBACK (serv, "/stop_forget", "f", stop_forget);
444                 REGISTER_CALLBACK (serv, "/set_punch_range", "", set_punch_range);
445                 REGISTER_CALLBACK (serv, "/set_punch_range", "f", set_punch_range);
446                 REGISTER_CALLBACK (serv, "/set_loop_range", "", set_loop_range);
447                 REGISTER_CALLBACK (serv, "/set_loop_range", "f", set_loop_range);
448                 REGISTER_CALLBACK (serv, "/set_session_range", "", set_session_range);
449                 REGISTER_CALLBACK (serv, "/set_session_range", "f", set_session_range);
450                 // /toggle_monitor_* not working (comented out)
451                 REGISTER_CALLBACK (serv, "/toggle_monitor_mute", "", toggle_monitor_mute);
452                 REGISTER_CALLBACK (serv, "/toggle_monitor_mute", "f", toggle_monitor_mute);
453                 REGISTER_CALLBACK (serv, "/toggle_monitor_dim", "", toggle_monitor_dim);
454                 REGISTER_CALLBACK (serv, "/toggle_monitor_dim", "f", toggle_monitor_dim);
455                 REGISTER_CALLBACK (serv, "/toggle_monitor_mono", "", toggle_monitor_mono);
456                 REGISTER_CALLBACK (serv, "/toggle_monitor_mono", "f", toggle_monitor_mono);
457                 REGISTER_CALLBACK (serv, "/quick_snapshot_switch", "", quick_snapshot_switch);
458                 REGISTER_CALLBACK (serv, "/quick_snapshot_switch", "f", quick_snapshot_switch);
459                 REGISTER_CALLBACK (serv, "/quick_snapshot_stay", "", quick_snapshot_stay);
460                 REGISTER_CALLBACK (serv, "/quick_snapshot_stay", "f", quick_snapshot_stay);
461                 REGISTER_CALLBACK (serv, "/fit_1_track", "", fit_1_track);
462                 REGISTER_CALLBACK (serv, "/fit_1_track", "f", fit_1_track);
463                 REGISTER_CALLBACK (serv, "/fit_2_tracks", "", fit_2_tracks);
464                 REGISTER_CALLBACK (serv, "/fit_2_tracks", "f", fit_2_tracks);
465                 REGISTER_CALLBACK (serv, "/fit_4_tracks", "", fit_4_tracks);
466                 REGISTER_CALLBACK (serv, "/fit_4_tracks", "f", fit_4_tracks);
467                 REGISTER_CALLBACK (serv, "/fit_8_tracks", "", fit_8_tracks);
468                 REGISTER_CALLBACK (serv, "/fit_8_tracks", "f", fit_8_tracks);
469                 REGISTER_CALLBACK (serv, "/fit_16_tracks", "", fit_16_tracks);
470                 REGISTER_CALLBACK (serv, "/fit_16_tracks", "f", fit_16_tracks);
471                 REGISTER_CALLBACK (serv, "/fit_32_tracks", "", fit_32_tracks);
472                 REGISTER_CALLBACK (serv, "/fit_32_tracks", "f", fit_32_tracks);
473                 REGISTER_CALLBACK (serv, "/fit_all_tracks", "", fit_all_tracks);
474                 REGISTER_CALLBACK (serv, "/fit_all_tracks", "f", fit_all_tracks);
475                 REGISTER_CALLBACK (serv, "/zoom_100_ms", "", zoom_100_ms);
476                 REGISTER_CALLBACK (serv, "/zoom_100_ms", "f", zoom_100_ms);
477                 REGISTER_CALLBACK (serv, "/zoom_1_sec", "", zoom_1_sec);
478                 REGISTER_CALLBACK (serv, "/zoom_1_sec", "f", zoom_1_sec);
479                 REGISTER_CALLBACK (serv, "/zoom_10_sec", "", zoom_10_sec);
480                 REGISTER_CALLBACK (serv, "/zoom_10_sec", "f", zoom_10_sec);
481                 REGISTER_CALLBACK (serv, "/zoom_1_min", "", zoom_1_min);
482                 REGISTER_CALLBACK (serv, "/zoom_1_min", "f", zoom_1_min);
483                 REGISTER_CALLBACK (serv, "/zoom_5_min", "", zoom_5_min);
484                 REGISTER_CALLBACK (serv, "/zoom_5_min", "f", zoom_5_min);
485                 REGISTER_CALLBACK (serv, "/zoom_10_min", "", zoom_10_min);
486                 REGISTER_CALLBACK (serv, "/zoom_10_min", "f", zoom_10_min);
487                 REGISTER_CALLBACK (serv, "/zoom_to_session", "", zoom_to_session);
488                 REGISTER_CALLBACK (serv, "/zoom_to_session", "f", zoom_to_session);
489                 REGISTER_CALLBACK (serv, "/temporal_zoom_in", "f", temporal_zoom_in);
490                 REGISTER_CALLBACK (serv, "/temporal_zoom_in", "", temporal_zoom_in);
491                 REGISTER_CALLBACK (serv, "/temporal_zoom_out", "", temporal_zoom_out);
492                 REGISTER_CALLBACK (serv, "/temporal_zoom_out", "f", temporal_zoom_out);
493                 REGISTER_CALLBACK (serv, "/scroll_up_1_track", "f", scroll_up_1_track);
494                 REGISTER_CALLBACK (serv, "/scroll_up_1_track", "", scroll_up_1_track);
495                 REGISTER_CALLBACK (serv, "/scroll_dn_1_track", "f", scroll_dn_1_track);
496                 REGISTER_CALLBACK (serv, "/scroll_dn_1_track", "", scroll_dn_1_track);
497                 REGISTER_CALLBACK (serv, "/scroll_up_1_page", "f", scroll_up_1_page);
498                 REGISTER_CALLBACK (serv, "/scroll_up_1_page", "", scroll_up_1_page);
499                 REGISTER_CALLBACK (serv, "/scroll_dn_1_page", "f", scroll_dn_1_page);
500                 REGISTER_CALLBACK (serv, "/scroll_dn_1_page", "", scroll_dn_1_page);
501                 REGISTER_CALLBACK (serv, "/bank_up", "", bank_up);
502                 REGISTER_CALLBACK (serv, "/bank_up", "f", bank_up);
503                 REGISTER_CALLBACK (serv, "/bank_down", "", bank_down);
504                 REGISTER_CALLBACK (serv, "/bank_down", "f", bank_down);
505                 REGISTER_CALLBACK (serv, "/master/gain", "f", master_set_gain);
506                 REGISTER_CALLBACK (serv, "/master/fader", "i", master_set_fader);
507                 REGISTER_CALLBACK (serv, "/master/mute", "i", master_set_mute);
508                 REGISTER_CALLBACK (serv, "/master/trimdB", "f", master_set_trim);
509                 REGISTER_CALLBACK (serv, "/master/pan_stereo_position", "f", master_set_pan_stereo_position);
510                 REGISTER_CALLBACK (serv, "/monitor/gain", "f", monitor_set_gain);
511                 REGISTER_CALLBACK (serv, "/monitor/fader", "i", monitor_set_fader);
512                 REGISTER_CALLBACK (serv, "/select/recenable", "i", sel_recenable);
513                 REGISTER_CALLBACK (serv, "/select/record_safe", "i", sel_recsafe);
514                 REGISTER_CALLBACK (serv, "/select/mute", "i", sel_mute);
515                 REGISTER_CALLBACK (serv, "/select/solo", "i", sel_solo);
516                 REGISTER_CALLBACK (serv, "/select/monitor_input", "i", sel_monitor_input);
517                 REGISTER_CALLBACK (serv, "/select/monitor_disk", "i", sel_monitor_disk);
518                 REGISTER_CALLBACK (serv, "/select/gain", "f", sel_gain);
519                 REGISTER_CALLBACK (serv, "/select/fader", "f", sel_fader);
520
521                 /* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these  */ 
522                 REGISTER_CALLBACK (serv, "/strip/mute", "ii", route_mute);
523                 REGISTER_CALLBACK (serv, "/strip/solo", "ii", route_solo);
524                 REGISTER_CALLBACK (serv, "/strip/recenable", "ii", route_recenable);
525                 REGISTER_CALLBACK (serv, "/strip/record_safe", "ii", route_recsafe);
526                 REGISTER_CALLBACK (serv, "/strip/monitor_input", "ii", route_monitor_input);
527                 REGISTER_CALLBACK (serv, "/strip/monitor_disk", "ii", route_monitor_disk);
528                 REGISTER_CALLBACK (serv, "/strip/select", "ii", strip_select);
529                 REGISTER_CALLBACK (serv, "/strip/gui_select", "ii", strip_gui_select);
530                 REGISTER_CALLBACK (serv, "/strip/gain", "if", route_set_gain_dB);
531                 REGISTER_CALLBACK (serv, "/strip/fader", "if", route_set_gain_fader);
532                 REGISTER_CALLBACK (serv, "/strip/trimabs", "if", route_set_trim_abs);
533                 REGISTER_CALLBACK (serv, "/strip/trimdB", "if", route_set_trim_dB);
534                 REGISTER_CALLBACK (serv, "/strip/pan_stereo_position", "if", route_set_pan_stereo_position);
535                 REGISTER_CALLBACK (serv, "/strip/pan_stereo_width", "if", route_set_pan_stereo_width);
536                 REGISTER_CALLBACK (serv, "/strip/plugin/parameter", "iiif", route_plugin_parameter);
537                 // prints to cerr only
538                 REGISTER_CALLBACK (serv, "/strip/plugin/parameter/print", "iii", route_plugin_parameter_print);
539                 REGISTER_CALLBACK (serv, "/strip/send/gainabs", "iif", route_set_send_gain_abs);
540                 REGISTER_CALLBACK (serv, "/strip/send/gaindB", "iif", route_set_send_gain_dB);
541
542                 /* still not-really-standardized query interface */
543                 //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
544                 //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
545
546                 // un/register_update args= s:ctrl s:returl s:retpath
547                 //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
548                 //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
549                 //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
550                 //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
551
552                 /* this is a special catchall handler,
553                  * register at the end so this is only called if no
554                  * other handler matches (used for debug) */
555                 lo_server_add_method (serv, 0, 0, _catchall, this);
556         }
557 }
558
559 bool
560 OSC::osc_input_handler (IOCondition ioc, lo_server srv)
561 {
562         if (ioc & ~IO_IN) {
563                 return false;
564         }
565
566         if (ioc & IO_IN) {
567                 lo_server_recv (srv);
568         }
569
570         return true;
571 }
572
573 std::string
574 OSC::get_server_url()
575 {
576         string url;
577         char * urlstr;
578
579         if (_osc_server) {
580                 urlstr = lo_server_get_url (_osc_server);
581                 url = urlstr;
582                 free (urlstr);
583         }
584
585         return url;
586 }
587
588 std::string
589 OSC::get_unix_server_url()
590 {
591         string url;
592         char * urlstr;
593
594         if (_osc_unix_server) {
595                 urlstr = lo_server_get_url (_osc_unix_server);
596                 url = urlstr;
597                 free (urlstr);
598         }
599
600         return url;
601 }
602
603 void
604 OSC::listen_to_route (boost::shared_ptr<Stripable> strip, lo_address addr)
605 {
606         /* avoid duplicate listens */
607
608         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); ++x) {
609
610                 OSCRouteObserver* ro;
611
612                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
613
614                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
615
616                         if (ro->strip() == strip && res == 0) {
617                                 return;
618                         }
619                 }
620         }
621
622         OSCSurface *s = get_surface(addr);
623         uint32_t sid = get_sid (strip->presentation_info().order() + 1, addr);
624         // above is zero based add 1
625         OSCRouteObserver* o = new OSCRouteObserver (strip, addr, sid, s->gainmode, s->feedback);
626         route_observers.push_back (o);
627
628         strip->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr<Stripable> (strip)), this);
629 }
630
631 void
632 OSC::drop_route (boost::weak_ptr<Stripable> wr)
633 {
634         boost::shared_ptr<Stripable> r = wr.lock ();
635
636         if (!r) {
637                 return;
638         }
639
640         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
641
642                 OSCRouteObserver* rc;
643
644                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
645
646                         if (rc->strip() == r) {
647                                 delete *x;
648                                 x = route_observers.erase (x);
649                         } else {
650                                 ++x;
651                         }
652                 } else {
653                         ++x;
654                 }
655         }
656 }
657
658 void
659 OSC::end_listen (boost::shared_ptr<Stripable> r, lo_address addr)
660 {
661         RouteObservers::iterator x;
662
663         // Remove the route observers
664         for (x = route_observers.begin(); x != route_observers.end();) {
665
666                 OSCRouteObserver* ro;
667
668                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
669
670                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
671
672                         if (ro->strip() == r && res == 0) {
673                                 delete *x;
674                                 x = route_observers.erase (x);
675                         }
676                         else {
677                                 ++x;
678                         }
679                 }
680                 else {
681                         ++x;
682                 }
683         }
684 }
685
686 void
687 OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg)
688 {
689         char* subpath;
690
691         subpath = (char*) malloc (len-15+1);
692         memcpy (subpath, path, len-15);
693         subpath[len-15] = '\0';
694
695         send_current_value (subpath, argv, argc, msg);
696
697         free (subpath);
698 }
699
700 void
701 OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg)
702 {
703         if (!session) {
704                 return;
705         }
706
707         lo_message reply = lo_message_new ();
708         boost::shared_ptr<Route> r;
709         int id;
710
711         lo_message_add_string (reply, path);
712
713         if (argc == 0) {
714                 lo_message_add_string (reply, "bad syntax");
715         } else {
716                 id = argv[0]->i;
717                 r = session->get_remote_nth_route (id);
718
719                 if (!r) {
720                         lo_message_add_string (reply, "not found");
721                 } else {
722
723                         if (strcmp (path, "/strip/state") == 0) {
724
725                                 if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
726                                         lo_message_add_string (reply, "AT");
727                                 } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
728                                         lo_message_add_string (reply, "MT");
729                                 } else {
730                                         lo_message_add_string (reply, "B");
731                                 }
732
733                                 lo_message_add_string (reply, r->name().c_str());
734                                 lo_message_add_int32 (reply, r->n_inputs().n_audio());
735                                 lo_message_add_int32 (reply, r->n_outputs().n_audio());
736                                 lo_message_add_int32 (reply, r->muted());
737                                 lo_message_add_int32 (reply, r->soloed());
738
739                         } else if (strcmp (path, "/strip/mute") == 0) {
740
741                                 lo_message_add_int32 (reply, (float) r->muted());
742
743                         } else if (strcmp (path, "/strip/solo") == 0) {
744
745                                 lo_message_add_int32 (reply, r->soloed());
746                         }
747                 }
748         }
749
750         lo_send_message (lo_message_get_source (msg), "#reply", reply);
751         lo_message_free (reply);
752 }
753
754 int
755 OSC::_catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data)
756 {
757         return ((OSC*)user_data)->catchall (path, types, argv, argc, data);
758 }
759
760 int
761 OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
762 {
763         size_t len;
764         int ret = 1; /* unhandled */
765
766         //cerr << "Received a message, path = " << path << " types = \""
767         //     << (types ? types : "NULL") << '"' << endl;
768
769         /* 15 for /#current_value plus 2 for /<path> */
770
771         len = strlen (path);
772
773         if (len >= 17 && !strcmp (&path[len-15], "/#current_value")) {
774                 current_value_query (path, len, argv, argc, msg);
775                 ret = 0;
776
777         } else if (strcmp (path, "/strip/listen") == 0) {
778
779                 cerr << "set up listener\n";
780
781                 lo_message reply = lo_message_new ();
782
783                 if (argc <= 0) {
784                         lo_message_add_string (reply, "syntax error");
785                 } else {
786                         for (int n = 0; n < argc; ++n) {
787
788                                 boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
789
790                                 if (!r) {
791                                         lo_message_add_string (reply, "not found");
792                                         cerr << "no such route\n";
793                                         break;
794                                 } else {
795                                         cerr << "add listener\n";
796                                         listen_to_route (r, lo_message_get_source (msg));
797                                         lo_message_add_int32 (reply, argv[n]->i);
798                                 }
799                         }
800                 }
801
802                 lo_send_message (lo_message_get_source (msg), "#reply", reply);
803                 lo_message_free (reply);
804
805                 ret = 0;
806
807         } else if (strcmp (path, "/strip/ignore") == 0) {
808
809                 for (int n = 0; n < argc; ++n) {
810
811                         boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
812
813                         if (r) {
814                                 end_listen (r, lo_message_get_source (msg));
815                         }
816                 }
817
818                 ret = 0;
819         } else if (argc == 1 && types[0] == 'f') { // single float -- probably TouchOSC
820                 if (!strncmp (path, "/strip/gain/", 12) && strlen (path) > 12) {
821                         // in dB
822                         int ssid = atoi (&path[12]);
823                         route_set_gain_dB (ssid, argv[0]->f, msg);
824                         ret = 0;
825                 }
826                 else if (!strncmp (path, "/strip/fader/", 13) && strlen (path) > 13) {
827                         // in fader position
828                         int ssid = atoi (&path[13]);
829                         route_set_gain_fader (ssid, argv[0]->f, msg);
830                         ret = 0;
831                 }
832                 else if (!strncmp (path, "/strip/trimdB/", 14) && strlen (path) > 14) {
833                         int ssid = atoi (&path[14]);
834                         route_set_trim_dB (ssid, argv[0]->f, msg);
835                         ret = 0;
836                 }
837                 else if (!strncmp (path, "/strip/mute/", 12) && strlen (path) > 12) {
838                         int ssid = atoi (&path[12]);
839                         route_mute (ssid, argv[0]->f == 1.0, msg);
840                         ret = 0;
841                 }
842                 else if (!strncmp (path, "/strip/solo/", 12) && strlen (path) > 12) {
843                         int ssid = atoi (&path[12]);
844                         route_solo (ssid, argv[0]->f == 1.0, msg);
845                         ret = 0;
846                 }
847                 else if (!strncmp (path, "/strip/monitor_input/", 21) && strlen (path) > 21) {
848                         int ssid = atoi (&path[21]);
849                         route_monitor_input (ssid, argv[0]->f == 1.0, msg);
850                         ret = 0;
851                 }
852                 else if (!strncmp (path, "/strip/monitor_disk/", 20) && strlen (path) > 20) {
853                         int ssid = atoi (&path[20]);
854                         route_monitor_disk (ssid, argv[0]->f == 1.0, msg);
855                         ret = 0;
856                 }
857                 else if (!strncmp (path, "/strip/recenable/", 17) && strlen (path) > 17) {
858                         int ssid = atoi (&path[17]);
859                         route_recenable (ssid, argv[0]->f == 1.0, msg);
860                         ret = 0;
861                 }
862                 else if (!strncmp (path, "/strip/record_safe/", 19) && strlen (path) > 19) {
863                         int ssid = atoi (&path[19]);
864                         route_recsafe (ssid, argv[0]->f == 1.0, msg);
865                         ret = 0;
866                 }
867                 else if (!strncmp (path, "/strip/select/", 14) && strlen (path) > 14) {
868                         int ssid = atoi (&path[14]);
869                         strip_select (ssid, argv[0]->f == 1.0, msg);
870                         ret = 0;
871                 }
872                 else if (!strncmp (path, "/strip/gui_select/", 18) && strlen (path) > 18) {
873                         int ssid = atoi (&path[18]);
874                         strip_gui_select (ssid, argv[0]->f == 1.0, msg);
875                         ret = 0;
876                 }
877         }
878
879         if ((ret && _debugmode == Unhandled)) {
880                 debugmsg (_("Unhandled OSC message"), path, types, argv, argc);
881         }
882
883         return ret;
884 }
885
886 void
887 OSC::debugmsg (const char *prefix, const char *path, const char* types, lo_arg **argv, int argc)
888 {
889         std::stringstream ss;
890         for (int i = 0; i < argc; ++i) {
891                 lo_type type = (lo_type)types[i];
892                         ss << " ";
893                 switch (type) {
894                         case LO_INT32:
895                                 ss << "i:" << argv[i]->i;
896                                 break;
897                         case LO_FLOAT:
898                                 ss << "f:" << argv[i]->f;
899                                 break;
900                         case LO_DOUBLE:
901                                 ss << "d:" << argv[i]->d;
902                                 break;
903                         case LO_STRING:
904                                 ss << "s:" << &argv[i]->s;
905                                 break;
906                         case LO_INT64:
907                                 ss << "h:" << argv[i]->h;
908                                 break;
909                         case LO_CHAR:
910                                 ss << "c:" << argv[i]->s;
911                                 break;
912                         case LO_TIMETAG:
913                                 ss << "<Timetag>";
914                                 break;
915                         case LO_BLOB:
916                                 ss << "<BLOB>";
917                                 break;
918                         case LO_TRUE:
919                                 ss << "#T";
920                                 break;
921                         case LO_FALSE:
922                                 ss << "#F";
923                                 break;
924                         case LO_NIL:
925                                 ss << "NIL";
926                                 break;
927                         case LO_INFINITUM:
928                                 ss << "#inf";
929                                 break;
930                         case LO_MIDI:
931                                 ss << "<MIDI>";
932                                 break;
933                         case LO_SYMBOL:
934                                 ss << "<SYMBOL>";
935                                 break;
936                         default:
937                                 ss << "< ?? >";
938                                 break;
939                 }
940         }
941         PBD::info << prefix << ": " << path << ss.str() << endmsg;
942 }
943
944 void
945 OSC::update_clock ()
946 {
947
948 }
949
950 // "Application Hook" Handlers //
951 void
952 OSC::session_loaded (Session& s)
953 {
954 //      lo_address listener = lo_address_new (NULL, "7770");
955 //      lo_send (listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str());
956 }
957
958 void
959 OSC::session_exported (std::string path, std::string name)
960 {
961         lo_address listener = lo_address_new (NULL, "7770");
962         lo_send (listener, "/session/exported", "ss", path.c_str(), name.c_str());
963         lo_address_free (listener);
964 }
965
966 // end "Application Hook" Handlers //
967
968 /* path callbacks */
969
970 int
971 OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, void */*data*/, void* /*user_data*/)
972 {
973 #if 0
974         const char* returl;
975
976         if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != s) {
977                 return 1;
978         }
979
980         const char *returl = argv[1]->s;
981         lo_address addr = find_or_cache_addr (returl);
982
983         const char *retpath = argv[2]->s;
984
985
986         if (strcmp (argv[0]->s, "transport_frame") == 0) {
987
988                 if (session) {
989                         lo_send (addr, retpath, "i", session->transport_frame());
990                 }
991
992         } else if (strcmp (argv[0]->s, "transport_speed") == 0) {
993
994                 if (session) {
995                         lo_send (addr, retpath, "i", session->transport_frame());
996                 }
997
998         } else if (strcmp (argv[0]->s, "transport_locked") == 0) {
999
1000                 if (session) {
1001                         lo_send (addr, retpath, "i", session->transport_frame());
1002                 }
1003
1004         } else if (strcmp (argv[0]->s, "punch_in") == 0) {
1005
1006                 if (session) {
1007                         lo_send (addr, retpath, "i", session->transport_frame());
1008                 }
1009
1010         } else if (strcmp (argv[0]->s, "punch_out") == 0) {
1011
1012                 if (session) {
1013                         lo_send (addr, retpath, "i", session->transport_frame());
1014                 }
1015
1016         } else if (strcmp (argv[0]->s, "rec_enable") == 0) {
1017
1018                 if (session) {
1019                         lo_send (addr, retpath, "i", session->transport_frame());
1020                 }
1021
1022         } else {
1023
1024                 /* error */
1025         }
1026 #endif
1027         return 0;
1028 }
1029
1030 void
1031 OSC::routes_list (lo_message msg)
1032 {
1033         if (!session) {
1034                 return;
1035         }
1036         for (int n = 0; n < (int) session->nroutes(); ++n) {
1037
1038                 boost::shared_ptr<Route> r = session->get_remote_nth_route (n);
1039
1040                 if (r) {
1041
1042                         lo_message reply = lo_message_new ();
1043
1044                         if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
1045                                 lo_message_add_string (reply, "AT");
1046                         } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
1047                                 lo_message_add_string (reply, "MT");
1048                         } else {
1049                                 lo_message_add_string (reply, "B");
1050                         }
1051
1052                         lo_message_add_string (reply, r->name().c_str());
1053                         lo_message_add_int32 (reply, r->n_inputs().n_audio());
1054                         lo_message_add_int32 (reply, r->n_outputs().n_audio());
1055                         lo_message_add_int32 (reply, r->muted());
1056                         lo_message_add_int32 (reply, r->soloed());
1057                         /* XXX Can only use order at this point */
1058                         lo_message_add_int32 (reply, r->presentation_info().order());
1059
1060                         if (boost::dynamic_pointer_cast<AudioTrack>(r)
1061                                         || boost::dynamic_pointer_cast<MidiTrack>(r)) {
1062
1063                                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
1064                                 lo_message_add_int32 (reply, (int32_t) t->rec_enable_control()->get_value());
1065                         }
1066
1067                         //Automatically listen to routes listed
1068                         listen_to_route(r, lo_message_get_source (msg));
1069
1070                         lo_send_message (lo_message_get_source (msg), "#reply", reply);
1071                         lo_message_free (reply);
1072                 }
1073         }
1074
1075         // Send end of listing message
1076         lo_message reply = lo_message_new ();
1077
1078         lo_message_add_string (reply, "end_route_list");
1079         lo_message_add_int64 (reply, session->frame_rate());
1080         lo_message_add_int64 (reply, session->current_end_frame());
1081
1082         lo_send_message (lo_message_get_source (msg), "#reply", reply);
1083
1084         lo_message_free (reply);
1085 }
1086
1087 int
1088 OSC::set_surface (uint32_t b_size, uint32_t strips, uint32_t fb, uint32_t gm, lo_message msg)
1089 {
1090         OSCSurface *s = get_surface(lo_message_get_source (msg));
1091         s->bank_size = b_size;
1092         s->strip_types = strips;
1093         //next line could be a call that finds out how many strips there are
1094         s->nstrips = session->nroutes(); // need to do this for strips
1095         s->feedback = fb;
1096         s->gainmode = gm;
1097         // set bank and strip feedback
1098         set_bank(s->bank, msg);
1099
1100         global_feedback (s->feedback, msg, s->gainmode);
1101         return 0;
1102 }
1103
1104 int
1105 OSC::set_surface_bank_size (uint32_t bs, lo_message msg)
1106 {
1107         OSCSurface *s = get_surface(lo_message_get_source (msg));
1108         s->bank_size = bs;
1109
1110         // set bank and strip feedback
1111         set_bank(s->bank, msg);
1112         return 0;
1113 }
1114
1115
1116 int
1117 OSC::set_surface_strip_types (uint32_t st, lo_message msg)
1118 {
1119         OSCSurface *s = get_surface(lo_message_get_source (msg));
1120         s->strip_types = st;
1121         //next line could be a call that finds out how many strips there are
1122         s->nstrips = session->nroutes(); // need to do this for strips
1123
1124         // set bank and strip feedback
1125         set_bank(s->bank, msg);
1126         return 0;
1127 }
1128
1129
1130 int
1131 OSC::set_surface_feedback (uint32_t fb, lo_message msg)
1132 {
1133         OSCSurface *s = get_surface(lo_message_get_source (msg));
1134         s->feedback = fb;
1135
1136         // set bank and strip feedback
1137         set_bank(s->bank, msg);
1138
1139         // Set global/master feedback
1140         global_feedback (s->feedback, msg, s->gainmode);
1141         return 0;
1142 }
1143
1144
1145 int
1146 OSC::set_surface_gainmode (uint32_t gm, lo_message msg)
1147 {
1148         OSCSurface *s = get_surface(lo_message_get_source (msg));
1149         s->gainmode = gm;
1150
1151         // set bank and strip feedback
1152         set_bank(s->bank, msg);
1153
1154         // Set global/master feedback
1155         global_feedback (s->feedback, msg, s->gainmode);
1156         return 0;
1157 }
1158
1159 OSC::OSCSurface *
1160 OSC::get_surface (lo_address addr)
1161 {
1162         string r_url;
1163         char * rurl;
1164         rurl = lo_address_get_url (addr);
1165         r_url = rurl;
1166         free (rurl);
1167         for (uint32_t it = 0; it < _surface.size(); ++it) {
1168                 //find setup for this server
1169                 if (!_surface[it].remote_url.find(r_url)){
1170                         return &_surface[it];
1171                 }
1172         }
1173         // No surface create one with default values
1174         OSCSurface s;
1175         s.remote_url = r_url;
1176         s.bank = 1;
1177         s.bank_size = 0; // need to find out how many strips there are
1178         s.nstrips = session->nroutes(); // may need to do this after MARK below
1179         s.strip_types = 31; // 31 is tracks, busses, and VCAs (no master/monitor)
1180         s.feedback = 0;
1181         s.gainmode = 0;
1182         //get sorted should go here
1183         _surface.push_back (s);
1184         //MARK
1185         return &_surface[_surface.size() - 1];
1186 }
1187
1188 // setup global feedback for a surface
1189 void
1190 OSC::global_feedback (bitset<32> feedback, lo_address msg, uint32_t gainmode)
1191 {
1192         // first destroy global observer for this surface
1193         GlobalObservers::iterator x;
1194
1195         for (x = global_observers.begin(); x != global_observers.end();) {
1196
1197                 OSCGlobalObserver* ro;
1198
1199                 if ((ro = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
1200
1201                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(lo_message_get_source (msg)));
1202
1203                         if (res == 0) {
1204                                 delete *x;
1205                                 x = global_observers.erase (x);
1206                         } else {
1207                                 ++x;
1208                         }
1209                 } else {
1210                         ++x;
1211                 }
1212         }
1213         if (feedback[4] || feedback[3] || feedback[5] || feedback[6]) {
1214                 // create a new Global Observer for this surface
1215                 //OSCSurface *s = get_surface (lo_message_get_source (msg));
1216                 OSCGlobalObserver* o = new OSCGlobalObserver (*session, lo_message_get_source (msg), gainmode, /*s->*/feedback);
1217                 global_observers.push_back (o);
1218         }
1219 }
1220
1221 /*
1222  * This gets called not only when bank changes but also:
1223  *  - bank size change
1224  *  - feedback change
1225  *  - strip types changes
1226  *  - fadermode changes
1227  *  - stripable creation/deletion/flag
1228  *  - to refresh what is "displayed"
1229  * Basically any time the bank needs to be rebuilt
1230  */
1231 int
1232 OSC::set_bank (uint32_t bank_start, lo_message msg)
1233 {
1234         if (!session) {
1235                 return -1;
1236         }
1237         //StripableList strips;
1238         //session->get_stripables (strips);
1239         // no nstripables yet
1240         if (!session->nroutes()) {
1241                 return -1;
1242         }
1243         // don't include monitor or master in count for now
1244         uint32_t nstrips;
1245         if (session->monitor_out ()) {
1246                 nstrips = session->nroutes() - 2;
1247         } else {
1248                 nstrips = session->nroutes() - 1;
1249         }
1250         // undo all listeners for this url
1251         for (int n = 0; n <= (int) nstrips; ++n) {
1252
1253                 boost::shared_ptr<Stripable> stp = session->get_remote_nth_stripable (n, PresentationInfo::Route);
1254
1255                 if (stp) {
1256                         end_listen (stp, lo_message_get_source (msg));
1257                 }
1258         }
1259
1260         OSCSurface *s = get_surface (lo_message_get_source (msg));
1261         uint32_t b_size;
1262
1263         if (!s->bank_size) {
1264                 // no banking
1265                 b_size = nstrips;
1266         } else {
1267                 b_size = s->bank_size;
1268         }
1269
1270         // Do limits checking - high end still not quite right
1271         if (bank_start < 1) bank_start = 1;
1272         if (b_size >= nstrips)  {
1273                 bank_start = 1;
1274         } else if ((bank_start > nstrips)) {
1275                 bank_start = (uint32_t)((nstrips - b_size) + 1);
1276         }
1277         //save bank in case we have had to change it
1278         s->bank = bank_start;
1279
1280         if (s->feedback[0] || s->feedback[1]) {
1281                 for (int n = bank_start; n < (int) (b_size + bank_start); ++n) {
1282                         // this next will eventually include strip types
1283                         boost::shared_ptr<Stripable> stp = session->get_remote_nth_stripable (n - 1, PresentationInfo::Route);
1284
1285                         if (stp) {
1286                         listen_to_route(stp, lo_message_get_source (msg));
1287                         }
1288                 }
1289         }
1290         return 0;
1291 }
1292
1293 int
1294 OSC::bank_up (lo_message msg)
1295 {
1296         if (!session) {
1297                 return -1;
1298         }
1299         OSCSurface *s = get_surface(lo_message_get_source (msg));
1300         set_bank (s->bank + s->bank_size, msg);
1301         return 0;
1302 }
1303
1304 int
1305 OSC::bank_down (lo_message msg)
1306 {
1307         if (!session) {
1308                 return -1;
1309         }
1310         OSCSurface *s = get_surface(lo_message_get_source (msg));
1311         if (s->bank < s->bank_size) {
1312                 set_bank (1, msg);
1313         } else {
1314                 set_bank (s->bank - s->bank_size, msg);
1315         }
1316         return 0;
1317 }
1318
1319 uint32_t
1320 OSC::get_sid (uint32_t rid, lo_address addr)
1321 {
1322         OSCSurface *s = get_surface(addr);
1323         return rid - s->bank + 1;
1324 }
1325
1326 uint32_t
1327 OSC::get_rid (uint32_t ssid, lo_address addr)
1328 {
1329         OSCSurface *s = get_surface(addr);
1330         return ssid + s->bank - 2;
1331 }
1332
1333 void
1334 OSC::transport_frame (lo_message msg)
1335 {
1336         if (!session) {
1337                 return;
1338         }
1339         framepos_t pos = session->transport_frame ();
1340
1341         lo_message reply = lo_message_new ();
1342         lo_message_add_int64 (reply, pos);
1343
1344         lo_send_message (lo_message_get_source (msg), "/transport_frame", reply);
1345
1346         lo_message_free (reply);
1347 }
1348
1349 void
1350 OSC::transport_speed (lo_message msg)
1351 {
1352         if (!session) {
1353                 return;
1354         }
1355         double ts = session->transport_speed ();
1356
1357         lo_message reply = lo_message_new ();
1358         lo_message_add_double (reply, ts);
1359
1360         lo_send_message (lo_message_get_source (msg), "/transport_speed", reply);
1361
1362         lo_message_free (reply);
1363 }
1364
1365 void
1366 OSC::record_enabled (lo_message msg)
1367 {
1368         if (!session) {
1369                 return;
1370         }
1371         int re = (int)session->get_record_enabled ();
1372
1373         lo_message reply = lo_message_new ();
1374         lo_message_add_int32 (reply, re);
1375
1376         lo_send_message (lo_message_get_source (msg), "/record_enabled", reply);
1377
1378         lo_message_free (reply);
1379 }
1380
1381 // master and monitor calls
1382 int
1383 OSC::master_set_gain (float dB)
1384 {
1385         if (!session) return -1;
1386         boost::shared_ptr<Stripable> s = session->master_out();
1387         if (s) {
1388                 if (dB < -192) {
1389                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
1390                 } else {
1391                         s->gain_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1392                 }
1393         }
1394         return 0;
1395 }
1396
1397 int
1398 OSC::master_set_fader (uint32_t position)
1399 {
1400         if (!session) return -1;
1401         boost::shared_ptr<Stripable> s = session->master_out();
1402         if (s) {
1403                 if ((position > 799.5) && (position < 800.5)) {
1404                         s->gain_control()->set_value (1.0, PBD::Controllable::NoGroup);
1405                 } else {
1406                         s->gain_control()->set_value (slider_position_to_gain_with_max (((float)position/1023), 2.0), PBD::Controllable::NoGroup);
1407                 }
1408         }
1409         return 0;
1410 }
1411
1412 int
1413 OSC::master_set_trim (float dB)
1414 {
1415         if (!session) return -1;
1416         boost::shared_ptr<Stripable> s = session->master_out();
1417
1418         if (s) {
1419                 s->trim_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1420         }
1421
1422         return 0;
1423 }
1424
1425 int
1426 OSC::master_set_pan_stereo_position (float position)
1427 {
1428         if (!session) return -1;
1429
1430         boost::shared_ptr<Stripable> s = session->master_out();
1431
1432         if (s) {
1433                 if (s->pan_azimuth_control()) {
1434                         s->pan_azimuth_control()->set_value (position, PBD::Controllable::NoGroup);
1435                 }
1436         }
1437
1438         return 0;
1439 }
1440
1441 int
1442 OSC::master_set_mute (uint32_t state)
1443 {
1444         if (!session) return -1;
1445
1446         boost::shared_ptr<Stripable> s = session->master_out();
1447
1448         if (s) {
1449                 s->mute_control()->set_value (state, PBD::Controllable::NoGroup);
1450         }
1451
1452         return 0;
1453 }
1454
1455 int
1456 OSC::monitor_set_gain (float dB)
1457 {
1458         if (!session) return -1;
1459         boost::shared_ptr<Stripable> s = session->monitor_out();
1460
1461         if (s) {
1462                 if (dB < -192) {
1463                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
1464                 } else {
1465                         s->gain_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1466                 }
1467         }
1468         return 0;
1469 }
1470
1471 int
1472 OSC::monitor_set_fader (uint32_t position)
1473 {
1474         if (!session) return -1;
1475         boost::shared_ptr<Stripable> s = session->monitor_out();
1476         if (s) {
1477                 if ((position > 799.5) && (position < 800.5)) {
1478                         s->gain_control()->set_value (1.0, PBD::Controllable::NoGroup);
1479                 } else {
1480                         s->gain_control()->set_value (slider_position_to_gain_with_max (((float)position/1023), 2.0), PBD::Controllable::NoGroup);
1481                 }
1482         }
1483         return 0;
1484 }
1485
1486 // strip calls
1487 int
1488 OSC::route_mute (int ssid, int yn, lo_message msg)
1489 {
1490         if (!session) return -1;
1491         int rid = get_rid (ssid, lo_message_get_source (msg));
1492
1493         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1494
1495         if (s) {
1496                 s->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1497         }
1498
1499         return 0;
1500 }
1501
1502 int
1503 OSC::sel_mute (uint32_t yn, lo_message msg)
1504 {
1505         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1506         return route_mute(sur->surface_sel, yn, msg);
1507 }
1508
1509 int
1510 OSC::route_solo (int ssid, int yn, lo_message msg)
1511 {
1512         if (!session) return -1;
1513         int rid = get_rid (ssid, lo_message_get_source (msg));
1514
1515         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1516
1517         if (s) {
1518                 s->solo_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1519         }
1520
1521         return 0;
1522 }
1523
1524 int
1525 OSC::sel_solo (uint32_t yn, lo_message msg)
1526 {
1527         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1528         return route_solo (sur->surface_sel, yn, msg);
1529 }
1530
1531 int
1532 OSC::sel_recenable (uint32_t yn, lo_message msg)
1533 {
1534         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1535         return route_recenable(sur->surface_sel, yn, msg);
1536 }
1537
1538 int
1539 OSC::route_recenable (int ssid, int yn, lo_message msg)
1540 {
1541         if (!session) return -1;
1542         int rid = get_rid (ssid, lo_message_get_source (msg));
1543
1544         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1545
1546         if (s) {
1547                 if (s->rec_enable_control()) {
1548                         s->rec_enable_control()->set_value (yn, PBD::Controllable::UseGroup);
1549                         if (s->rec_enable_control()->get_value()) {
1550                                 return 0;
1551                         }
1552                 }
1553         }
1554         // hmm, not set for whatever reason tell surface
1555         return route_send_fail ("recenable", ssid, 0, msg);
1556 }
1557
1558 int
1559 OSC::sel_recsafe (uint32_t yn, lo_message msg)
1560 {
1561         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1562         return route_recsafe(sur->surface_sel, yn, msg);
1563 }
1564
1565 int
1566 OSC::route_recsafe (int ssid, int yn, lo_message msg)
1567 {
1568         if (!session) return -1;
1569         int rid = get_rid (ssid, lo_message_get_source (msg));
1570
1571         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1572         if (s) {
1573                 if (s->rec_safe_control()) {
1574                         s->rec_safe_control()->set_value (yn, PBD::Controllable::UseGroup);
1575                         if (s->rec_safe_control()->get_value()) {
1576                                 return 0;
1577                         }
1578                 }
1579         }
1580         // hmm, not set for whatever reason tell surface
1581         return route_send_fail ("record_safe", ssid, 0, msg);
1582 }
1583
1584 int
1585 OSC::route_monitor_input (int ssid, int yn, lo_message msg)
1586 {
1587         if (!session) return -1;
1588         int rid = get_rid (ssid, lo_message_get_source (msg));
1589
1590         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1591
1592         if (s) {
1593                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
1594                 if (track) {
1595                         track->monitoring_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1596                 } else {
1597                         route_send_fail ("monitor_input", ssid, 0, msg);
1598                 }
1599
1600         }
1601
1602         return 0;
1603 }
1604
1605 int
1606 OSC::sel_monitor_input (uint32_t yn, lo_message msg)
1607 {
1608         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1609         return route_monitor_input(sur->surface_sel, yn, msg);
1610 }
1611
1612 int
1613 OSC::route_monitor_disk (int ssid, int yn, lo_message msg)
1614 {
1615         if (!session) return -1;
1616         int rid = get_rid (ssid, lo_message_get_source (msg));
1617
1618         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1619
1620         if (s) {
1621                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
1622                 if (track) {
1623                         track->monitoring_control()->set_value (yn ? 2.0 : 0.0, PBD::Controllable::NoGroup);
1624                 } else {
1625                         route_send_fail ("monitor_disk", ssid, 0, msg);
1626                 }
1627
1628         }
1629
1630         return 0;
1631 }
1632
1633 int
1634 OSC::sel_monitor_disk (uint32_t yn, lo_message msg)
1635 {
1636         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1637         return route_monitor_disk(sur->surface_sel, yn, msg);
1638 }
1639
1640 int
1641 OSC::strip_select (int ssid, int yn, lo_message msg)
1642 {
1643         //ignore button release
1644         if (!yn) return 0;
1645
1646         if (!session) {
1647                 route_send_fail ("select", ssid, 0, msg);
1648                 return -1;
1649         }
1650         int rid = get_rid (ssid, lo_message_get_source (msg));
1651         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1652         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1653         delete sur->sel_obs;
1654
1655         if (s) {
1656                 sur->surface_sel = ssid;
1657                 OSCSelectObserver* sel_fb = new OSCSelectObserver (s, lo_message_get_source (msg), ssid, sur->gainmode, sur->feedback);
1658                 sur->sel_obs = sel_fb;
1659         } else {
1660                 route_send_fail ("select", ssid, 0 , msg);
1661         }
1662         int b_s = sur->bank_size;
1663         if (!b_s) { // bank size 0 means we need to know how many strips there are.
1664                 b_s = sur->nstrips;
1665         }
1666         for (int i = 1;  i <= b_s; i++) {
1667                         if (i==ssid) {
1668                                 string path = "/strip/select";
1669                                 lo_message reply = lo_message_new ();
1670                                 if (sur->feedback[2]) {
1671                                         ostringstream os;
1672                                         os << path << "/" << ssid;
1673                                         path = os.str();
1674                                 } else {
1675                                 lo_message_add_int32 (reply, ssid);
1676                                 }
1677                                 lo_message_add_float (reply, (float) 1);
1678
1679                                 lo_send_message (lo_message_get_source (msg), path.c_str(), reply);
1680                                 lo_message_free (reply);
1681                         } else {
1682                                 route_send_fail ("select", i, 0, msg);
1683                         }
1684         }
1685
1686         return 0;
1687 }
1688
1689 int
1690 OSC::strip_gui_select (int ssid, int yn, lo_message msg)
1691 {
1692         //ignore button release
1693         if (!yn) return 0;
1694
1695         if (!session) {
1696                 route_send_fail ("gui_select", ssid, 0, msg);
1697                 return -1;
1698         }
1699         int ret = strip_select (ssid, yn, msg);
1700         if (ret != 0) {
1701                 return ret;
1702         }
1703         int rid = get_rid (ssid, lo_message_get_source (msg));
1704         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1705         //OSCSurface *sur = get_surface(lo_message_get_source (msg));
1706
1707         if (s) {
1708                 //s->set_select();
1709                 //sur->surface_sel = ssid;
1710         } else {
1711                 route_send_fail ("gui_select", ssid, 0, msg);
1712         }
1713
1714         return 0;
1715 }
1716
1717 int
1718 OSC::route_set_gain_abs (int rid, float level, lo_message msg)
1719 {
1720         if (!session) return -1;
1721         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1722
1723         if (s) {
1724                 s->gain_control()->set_value (level, PBD::Controllable::NoGroup);
1725         }
1726
1727         return 0;
1728 }
1729
1730 int
1731 OSC::route_set_gain_dB (int ssid, float dB, lo_message msg)
1732 {
1733         if (!session) {
1734                 route_send_fail ("gain", ssid, -193, msg);
1735                 return -1;
1736         }
1737         int ret;
1738         int rid = get_rid (ssid, lo_message_get_source (msg));
1739         if (dB < -192) {
1740                 ret = route_set_gain_abs (rid, 0.0, msg);
1741         } else {
1742                 ret = route_set_gain_abs (rid, dB_to_coefficient (dB), msg);
1743         }
1744         if (ret != 0) {
1745                 route_send_fail ("gain", ssid, 0, msg);
1746         }
1747         return ret;
1748 }
1749
1750 int
1751 OSC::sel_gain (float val, lo_message msg)
1752 {
1753         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1754         return route_set_gain_dB(sur->surface_sel, val, msg);
1755 }
1756
1757 int
1758 OSC::route_set_gain_fader (int ssid, float pos, lo_message msg)
1759 {
1760         if (!session) {
1761                 route_send_fail ("fader", ssid, 0, msg);
1762                 return -1;
1763         }
1764         int ret;
1765         int rid = get_rid (ssid, lo_message_get_source (msg));
1766         if ((pos > 799.5) && (pos < 800.5)) {
1767                 ret = route_set_gain_abs (rid, 1.0, msg);
1768         } else {
1769                 ret = route_set_gain_abs (rid, slider_position_to_gain_with_max ((pos/1023), 2.0), msg);
1770         }
1771         if (ret != 0) {
1772                 route_send_fail ("fader", ssid, 0, msg);
1773         }
1774         return ret;
1775 }
1776
1777 int
1778 OSC::sel_fader (float val, lo_message msg)
1779 {
1780         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1781         return route_set_gain_fader(sur->surface_sel, val, msg);
1782 }
1783
1784 int
1785 OSC::route_set_trim_abs (int ssid, float level, lo_message msg)
1786 {
1787         if (!session) return -1;
1788         int rid = get_rid (ssid, lo_message_get_source (msg));
1789
1790         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1791
1792         if (s) {
1793                 if (s->trim_control()) {
1794                         s->trim_control()->set_value (level, PBD::Controllable::NoGroup);
1795                 }
1796
1797         }
1798
1799         return 0;
1800 }
1801
1802 int
1803 OSC::route_set_trim_dB (int ssid, float dB, lo_message msg)
1804 {
1805         return route_set_trim_abs(ssid, dB_to_coefficient (dB), msg);
1806 }
1807
1808
1809 int
1810 OSC::route_set_pan_stereo_position (int ssid, float pos, lo_message msg)
1811 {
1812         if (!session) return -1;
1813         int rid = get_rid (ssid, lo_message_get_source (msg));
1814
1815         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1816
1817         if (s) {
1818                 if(s->pan_azimuth_control()) {
1819                         s->pan_azimuth_control()->set_value (pos, PBD::Controllable::NoGroup);
1820                 }
1821         }
1822
1823         return 0;
1824
1825 }
1826
1827 int
1828 OSC::route_set_pan_stereo_width (int ssid, float pos, lo_message msg)
1829 {
1830         if (!session) return -1;
1831         int rid = get_rid (ssid, lo_message_get_source (msg));
1832
1833         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1834
1835         if (s) {
1836                 if (s->pan_width_control()) {
1837                         s->pan_width_control()->set_value (pos, PBD::Controllable::NoGroup);
1838                 }
1839         }
1840
1841         return 0;
1842
1843 }
1844
1845 int
1846 OSC::route_set_send_gain_abs (int ssid, int sid, float val, lo_message msg)
1847 {
1848         if (!session) {
1849                 return -1;
1850         }
1851         int rid = get_rid (ssid, lo_message_get_source (msg));
1852
1853         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1854
1855         if (!s) {
1856                 return -1;
1857         }
1858
1859         /* revert to zero-based counting */
1860
1861         if (sid > 0) {
1862                 --sid;
1863         }
1864
1865         if (s->send_level_controllable (sid)) {
1866                 s->send_level_controllable (sid)->set_value (val, PBD::Controllable::NoGroup);
1867         }
1868
1869         return 0;
1870 }
1871
1872 int
1873 OSC::route_set_send_gain_dB (int ssid, int sid, float val, lo_message msg)
1874 {
1875         return route_set_send_gain_abs (ssid, sid, dB_to_coefficient (val), msg);
1876 }
1877
1878 int
1879 OSC::route_plugin_parameter (int ssid, int piid, int par, float val, lo_message msg)
1880 {
1881         if (!session)
1882                 return -1;
1883         int rid = get_rid (ssid, lo_message_get_source (msg));
1884
1885         boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
1886
1887         if (!r) {
1888                 PBD::error << "OSC: Invalid Remote Control ID '" << rid << "'" << endmsg;
1889                 return -1;
1890         }
1891
1892         boost::shared_ptr<Processor> redi=r->nth_plugin (piid);
1893
1894         if (!redi) {
1895                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << rid << "'" << endmsg;
1896                 return -1;
1897         }
1898
1899         boost::shared_ptr<PluginInsert> pi;
1900
1901         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
1902                 PBD::error << "OSC: given processor # " << piid << " on RID '" << rid << "' is not a Plugin." << endmsg;
1903                 return -1;
1904         }
1905
1906         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
1907         bool ok=false;
1908
1909         uint32_t controlid = pip->nth_parameter (par,ok);
1910
1911         if (!ok) {
1912                 PBD::error << "OSC: Cannot find parameter # " << par <<  " for plugin # " << piid << " on RID '" << rid << "'" << endmsg;
1913                 return -1;
1914         }
1915
1916         if (!pip->parameter_is_input(controlid)) {
1917                 PBD::error << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << rid << "' is not a control input" << endmsg;
1918                 return -1;
1919         }
1920
1921         ParameterDescriptor pd;
1922         pi->plugin()->get_parameter_descriptor (controlid,pd);
1923
1924         if (val >= pd.lower && val <= pd.upper) {
1925
1926                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
1927                 // cerr << "parameter:" << redi->describe_parameter(controlid) << " val:" << val << "\n";
1928                 c->set_value (val, PBD::Controllable::NoGroup);
1929         } else {
1930                 PBD::warning << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << rid << "' is out of range" << endmsg;
1931                 PBD::info << "OSC: Valid range min=" << pd.lower << " max=" << pd.upper << endmsg;
1932         }
1933
1934         return 0;
1935 }
1936
1937 //prints to cerr only
1938 int
1939 OSC::route_plugin_parameter_print (int ssid, int piid, int par, lo_message msg)
1940 {
1941         if (!session) {
1942                 return -1;
1943         }
1944         int rid = get_rid (ssid, lo_message_get_source (msg));
1945
1946         boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
1947
1948         if (!r) {
1949                 return -1;
1950         }
1951
1952         boost::shared_ptr<Processor> redi=r->nth_processor (piid);
1953
1954         if (!redi) {
1955                 return -1;
1956         }
1957
1958         boost::shared_ptr<PluginInsert> pi;
1959
1960         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
1961                 return -1;
1962         }
1963
1964         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
1965         bool ok=false;
1966
1967         uint32_t controlid = pip->nth_parameter (par,ok);
1968
1969         if (!ok) {
1970                 return -1;
1971         }
1972
1973         ParameterDescriptor pd;
1974
1975         if (pi->plugin()->get_parameter_descriptor (controlid, pd) == 0) {
1976                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
1977
1978                 cerr << "parameter:     " << redi->describe_parameter(controlid)  << "\n";
1979                 cerr << "current value: " << c->get_value ();
1980                 cerr << "lower value:   " << pd.lower << "\n";
1981                 cerr << "upper value:   " << pd.upper << "\n";
1982         }
1983
1984         return 0;
1985 }
1986
1987 // timer callbacks
1988 bool
1989 OSC::periodic (void)
1990 {
1991         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end(); x++) {
1992
1993                 OSCGlobalObserver* go;
1994
1995                 if ((go = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
1996                         go->tick();
1997                 }
1998         }
1999         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); x++) {
2000
2001                 OSCRouteObserver* ro;
2002
2003                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
2004                         ro->tick();
2005                 }
2006         }
2007         for (uint32_t it = 0; it < _surface.size(); ++it) {
2008                 OSCSurface* sur = &_surface[it];
2009                 OSCSelectObserver* so;
2010                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
2011                         so->tick();
2012                 }
2013         }
2014         return true;
2015 }
2016
2017 int
2018 OSC::route_send_fail (string path, uint32_t ssid, float val, lo_message msg)
2019 {
2020         OSCSurface *sur = get_surface(lo_message_get_source (msg));
2021
2022         ostringstream os;
2023         lo_message reply = lo_message_new ();
2024         if (sur->feedback[2]) {
2025                 os << "/strip/" << path << "/" << ssid;
2026         } else {
2027                 os << "/strip/" << path;
2028                 lo_message_add_int32 (reply, ssid);
2029         }
2030         string str_pth = os.str();
2031         lo_message_add_float (reply, (float) val);
2032
2033         lo_send_message (lo_message_get_source (msg), str_pth.c_str(), reply);
2034         lo_message_free (reply);
2035         if (sur->surface_sel == ssid) {
2036                 os.str("");
2037                 os << "/select/" << path;
2038                 string sel_pth = os.str();
2039                 reply = lo_message_new ();
2040                 lo_message_add_float (reply, (float) val);
2041                 lo_send_message (lo_message_get_source (msg), sel_pth.c_str(), reply);
2042                 lo_message_free (reply);
2043         }
2044
2045         return 0;
2046 }
2047
2048 XMLNode&
2049 OSC::get_state ()
2050 {
2051         XMLNode& node (ControlProtocol::get_state());
2052         node.add_property("debugmode", (int) _debugmode); // TODO: enum2str
2053         return node;
2054 }
2055
2056 int
2057 OSC::set_state (const XMLNode& node, int version)
2058 {
2059         if (ControlProtocol::set_state (node, version)) {
2060                 return -1;
2061         }
2062         XMLProperty const * p = node.property (X_("debugmode"));
2063         if (p) {
2064                 _debugmode = OSCDebugMode (PBD::atoi(p->value ()));
2065         }
2066
2067         return 0;
2068 }