OSC: set surface should reset custom mode
[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.h>
30
31 #include "pbd/control_math.h"
32 #include <pbd/convert.h>
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/route_group.h"
41 #include "ardour/audio_track.h"
42 #include "ardour/midi_track.h"
43 #include "ardour/vca.h"
44 #include "ardour/monitor_control.h"
45 #include "ardour/dB.h"
46 #include "ardour/filesystem_paths.h"
47 #include "ardour/panner.h"
48 #include "ardour/plugin.h"
49 #include "ardour/plugin_insert.h"
50 #include "ardour/presentation_info.h"
51 #include "ardour/profile.h"
52 #include "ardour/send.h"
53 #include "ardour/internal_send.h"
54 #include "ardour/phase_control.h"
55 #include "ardour/solo_isolate_control.h"
56 #include "ardour/solo_safe_control.h"
57 #include "ardour/vca_manager.h"
58
59 #include "osc_select_observer.h"
60 #include "osc.h"
61 #include "osc_controllable.h"
62 #include "osc_route_observer.h"
63 #include "osc_global_observer.h"
64 #include "osc_cue_observer.h"
65 #include "pbd/i18n.h"
66
67 using namespace ARDOUR;
68 using namespace std;
69 using namespace Glib;
70 using namespace ArdourSurface;
71
72 #include "pbd/abstract_ui.cc" // instantiate template
73
74 OSC* OSC::_instance = 0;
75
76 #ifdef DEBUG
77 static void error_callback(int num, const char *m, const char *path)
78 {
79         fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
80 }
81 #else
82 static void error_callback(int, const char *, const char *)
83 {
84
85 }
86 #endif
87
88 OSC::OSC (Session& s, uint32_t port)
89         : ControlProtocol (s, X_("Open Sound Control (OSC)"))
90         , AbstractUI<OSCUIRequest> (name())
91         , local_server (0)
92         , remote_server (0)
93         , _port(port)
94         , _ok (true)
95         , _shutdown (false)
96         , _osc_server (0)
97         , _osc_unix_server (0)
98         , _debugmode (Off)
99         , address_only (true)
100         , remote_port ("8000")
101         , default_banksize (0)
102         , default_strip (159)
103         , default_feedback (0)
104         , default_gainmode (0)
105         , default_send_size (0)
106         , default_plugin_size (0)
107         , tick (true)
108         , bank_dirty (false)
109         , observer_busy (true)
110         , scrub_speed (0)
111         , gui (0)
112 {
113         _instance = this;
114
115         session->Exported.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::session_exported, this, _1, _2), this);
116 }
117
118 OSC::~OSC()
119 {
120         tick = false;
121         stop ();
122         tear_down_gui ();
123         _instance = 0;
124 }
125
126 void*
127 OSC::request_factory (uint32_t num_requests)
128 {
129         /* AbstractUI<T>::request_buffer_factory() is a template method only
130            instantiated in this source module. To provide something visible for
131            use in the interface/descriptor, we have this static method that is
132            template-free.
133         */
134         return request_buffer_factory (num_requests);
135 }
136
137 void
138 OSC::do_request (OSCUIRequest* req)
139 {
140         if (req->type == CallSlot) {
141
142                 call_slot (MISSING_INVALIDATOR, req->the_slot);
143
144         } else if (req->type == Quit) {
145
146                 stop ();
147         }
148 }
149
150 int
151 OSC::set_active (bool yn)
152 {
153         if (yn != active()) {
154
155                 if (yn) {
156                         if (start ()) {
157                                 return -1;
158                         }
159                 } else {
160                         if (stop ()) {
161                                 return -1;
162                         }
163                 }
164
165         }
166
167         return ControlProtocol::set_active (yn);
168 }
169
170 bool
171 OSC::get_active () const
172 {
173         return _osc_server != 0;
174 }
175
176 int
177 OSC::start ()
178 {
179         char tmpstr[255];
180
181         if (_osc_server) {
182                 /* already started */
183                 return 0;
184         }
185
186         for (int j=0; j < 20; ++j) {
187                 snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
188
189                 //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
190                 //      break;
191                 //}
192
193                 if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
194                         break;
195                 }
196
197 #ifdef DEBUG
198                 cerr << "can't get osc at port: " << _port << endl;
199 #endif
200                 _port++;
201                 continue;
202         }
203
204         if (!_osc_server) {
205                 return 1;
206         }
207
208 #ifdef ARDOUR_OSC_UNIX_SERVER
209
210         // APPEARS sluggish for now
211
212         // attempt to create unix socket server too
213
214         snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
215         int fd = mkstemp(tmpstr);
216
217         if (fd >= 0 ) {
218                 ::g_unlink (tmpstr);
219                 close (fd);
220
221                 _osc_unix_server = lo_server_new (tmpstr, error_callback);
222
223                 if (_osc_unix_server) {
224                         _osc_unix_socket_path = tmpstr;
225                 }
226         }
227 #endif
228
229         PBD::info << "OSC @ " << get_server_url () << endmsg;
230
231         std::string url_file;
232
233         if (find_file (ardour_config_search_path(), "osc_url", url_file)) {
234                 _osc_url_file = url_file;
235                 if (g_file_set_contents (_osc_url_file.c_str(), get_server_url().c_str(), -1, NULL)) {
236                         cerr << "Couldn't write '" <<  _osc_url_file << "'" <<endl;
237                 }
238         }
239
240         observer_busy = false;
241         register_callbacks();
242
243         session_loaded (*session);
244
245         // lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
246
247         /* startup the event loop thread */
248
249         BaseUI::run ();
250
251         // start timers for metering, timecode and heartbeat.
252         // timecode and metering run at 100
253         Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
254         periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &OSC::periodic));
255         periodic_timeout->attach (main_loop()->get_context());
256
257         // catch track reordering
258         // receive routes added
259         session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_routes_added, this, _1), this);
260         // receive VCAs added
261         session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_vca_added, this, _1), this);
262         // order changed
263         PresentationInfo::Change.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
264
265         _select = ControlProtocol::first_selected_stripable();
266         if(!_select) {
267                 _select = session->master_out ();
268         }
269
270         return 0;
271 }
272
273 void
274 OSC::thread_init ()
275 {
276         pthread_set_name (event_loop_name().c_str());
277
278         if (_osc_unix_server) {
279                 Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
280                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_unix_server));
281                 src->attach (_main_loop->get_context());
282                 local_server = src->gobj();
283                 g_source_ref (local_server);
284         }
285
286         if (_osc_server) {
287 #ifdef PLATFORM_WINDOWS
288                 Glib::RefPtr<IOChannel> chan = Glib::IOChannel::create_from_win32_socket (lo_server_get_socket_fd (_osc_server));
289                 Glib::RefPtr<IOSource> src  = IOSource::create (chan, IO_IN|IO_HUP|IO_ERR);
290 #else
291                 Glib::RefPtr<IOSource> src  = IOSource::create (lo_server_get_socket_fd (_osc_server), IO_IN|IO_HUP|IO_ERR);
292 #endif
293                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_server));
294                 src->attach (_main_loop->get_context());
295                 remote_server = src->gobj();
296                 g_source_ref (remote_server);
297         }
298
299         PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
300         SessionEvent::create_per_thread_pool (event_loop_name(), 128);
301 }
302
303 int
304 OSC::stop ()
305 {
306         periodic_connection.disconnect ();
307         session_connections.drop_connections ();
308
309         // clear surfaces
310         observer_busy = true;
311         for (uint32_t it = 0; it < _surface.size (); ++it) {
312                 OSCSurface* sur = &_surface[it];
313                 surface_destroy (sur);
314         }
315         _surface.clear();
316
317         /* stop main loop */
318         if (local_server) {
319                 g_source_destroy (local_server);
320                 g_source_unref (local_server);
321                 local_server = 0;
322         }
323
324         if (remote_server) {
325                 g_source_destroy (remote_server);
326                 g_source_unref (remote_server);
327                 remote_server = 0;
328         }
329
330         BaseUI::quit ();
331
332         if (_osc_server) {
333                 lo_server_free (_osc_server);
334                 _osc_server = 0;
335         }
336
337         if (_osc_unix_server) {
338                 lo_server_free (_osc_unix_server);
339                 _osc_unix_server = 0;
340         }
341
342         if (!_osc_unix_socket_path.empty()) {
343                 ::g_unlink (_osc_unix_socket_path.c_str());
344         }
345
346         if (!_osc_url_file.empty() ) {
347                 ::g_unlink (_osc_url_file.c_str() );
348         }
349
350         return 0;
351 }
352
353 void
354 OSC::surface_destroy (OSCSurface* sur)
355 {
356         OSCSelectObserver* so;
357         if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
358                 so->clear_observer ();
359                 delete so;
360                 sur->sel_obs = 0;
361                 PBD::ScopedConnection pc = sur->proc_connection;
362                 pc.disconnect ();
363         }
364
365         OSCCueObserver* co;
366         if ((co = dynamic_cast<OSCCueObserver*>(sur->cue_obs)) != 0) {
367                 delete co;
368                 sur->cue_obs = 0;
369                 sur->sends.clear ();
370         }
371
372         OSCGlobalObserver* go;
373         if ((go = dynamic_cast<OSCGlobalObserver*>(sur->global_obs)) != 0) {
374                 go->clear_observer ();
375                 delete go;
376                 sur->global_obs = 0;
377         }
378         uint32_t st_end = sur->observers.size ();
379
380         for (uint32_t i = 0; i < st_end; i++) {
381                 OSCRouteObserver* ro;
382                 if ((ro = dynamic_cast<OSCRouteObserver*>(sur->observers[i])) != 0) {
383                         ro->clear_strip ();
384                         delete ro;
385                         ro = 0;
386                 }
387         }
388         sur->observers.clear();
389 }
390
391
392 void
393 OSC::register_callbacks()
394 {
395         lo_server srvs[2];
396         lo_server serv;
397
398         srvs[0] = _osc_server;
399         srvs[1] = _osc_unix_server;
400
401         for (size_t i = 0; i < 2; ++i) {
402
403                 if (!srvs[i]) {
404                         continue;
405                 }
406
407                 serv = srvs[i];
408
409
410 #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this)
411
412                 // Some controls have optional "f" for feedback or touchosc
413                 // http://hexler.net/docs/touchosc-controls-reference
414
415                 REGISTER_CALLBACK (serv, X_("/refresh"), "", refresh_surface);
416                 REGISTER_CALLBACK (serv, X_("/refresh"), "f", refresh_surface);
417                 REGISTER_CALLBACK (serv, X_("/strip/list"), "", routes_list);
418                 REGISTER_CALLBACK (serv, X_("/strip/list"), "f", routes_list);
419                 REGISTER_CALLBACK (serv, X_("/group/list"), "", group_list);
420                 REGISTER_CALLBACK (serv, X_("/group/list"), "f", group_list);
421                 REGISTER_CALLBACK (serv, X_("/strip/custom/mode"), "f", custom_mode);
422                 REGISTER_CALLBACK (serv, X_("/strip/custom/clear"), "f", custom_clear);
423                 REGISTER_CALLBACK (serv, X_("/strip/custom/clear"), "", custom_clear);
424                 REGISTER_CALLBACK (serv, X_("/surface/list"), "", surface_list);
425                 REGISTER_CALLBACK (serv, X_("/surface/list"), "f", surface_list);
426                 REGISTER_CALLBACK (serv, X_("/add_marker"), "", add_marker);
427                 REGISTER_CALLBACK (serv, X_("/add_marker"), "f", add_marker);
428                 REGISTER_CALLBACK (serv, X_("/access_action"), "s", access_action);
429                 REGISTER_CALLBACK (serv, X_("/loop_toggle"), "", loop_toggle);
430                 REGISTER_CALLBACK (serv, X_("/loop_toggle"), "f", loop_toggle);
431                 REGISTER_CALLBACK (serv, X_("/loop_location"), "ii", loop_location);
432                 REGISTER_CALLBACK (serv, X_("/goto_start"), "", goto_start);
433                 REGISTER_CALLBACK (serv, X_("/goto_start"), "f", goto_start);
434                 REGISTER_CALLBACK (serv, X_("/goto_end"), "", goto_end);
435                 REGISTER_CALLBACK (serv, X_("/goto_end"), "f", goto_end);
436                 REGISTER_CALLBACK (serv, X_("/scrub"), "f", scrub);
437                 REGISTER_CALLBACK (serv, X_("/jog"), "f", jog);
438                 REGISTER_CALLBACK (serv, X_("/jog/mode"), "f", jog_mode);
439                 REGISTER_CALLBACK (serv, X_("/rewind"), "", rewind);
440                 REGISTER_CALLBACK (serv, X_("/rewind"), "f", rewind);
441                 REGISTER_CALLBACK (serv, X_("/ffwd"), "", ffwd);
442                 REGISTER_CALLBACK (serv, X_("/ffwd"), "f", ffwd);
443                 REGISTER_CALLBACK (serv, X_("/transport_stop"), "", transport_stop);
444                 REGISTER_CALLBACK (serv, X_("/transport_stop"), "f", transport_stop);
445                 REGISTER_CALLBACK (serv, X_("/transport_play"), "", transport_play);
446                 REGISTER_CALLBACK (serv, X_("/transport_play"), "f", transport_play);
447                 REGISTER_CALLBACK (serv, X_("/transport_frame"), "", transport_sample);
448                 REGISTER_CALLBACK (serv, X_("/transport_speed"), "", transport_speed);
449                 REGISTER_CALLBACK (serv, X_("/record_enabled"), "", record_enabled);
450                 REGISTER_CALLBACK (serv, X_("/set_transport_speed"), "f", set_transport_speed);
451                 // locate ii is position and bool roll
452                 REGISTER_CALLBACK (serv, X_("/locate"), "ii", locate);
453                 REGISTER_CALLBACK (serv, X_("/save_state"), "", save_state);
454                 REGISTER_CALLBACK (serv, X_("/save_state"), "f", save_state);
455                 REGISTER_CALLBACK (serv, X_("/prev_marker"), "", prev_marker);
456                 REGISTER_CALLBACK (serv, X_("/prev_marker"), "f", prev_marker);
457                 REGISTER_CALLBACK (serv, X_("/next_marker"), "", next_marker);
458                 REGISTER_CALLBACK (serv, X_("/next_marker"), "f", next_marker);
459                 REGISTER_CALLBACK (serv, X_("/undo"), "", undo);
460                 REGISTER_CALLBACK (serv, X_("/undo"), "f", undo);
461                 REGISTER_CALLBACK (serv, X_("/redo"), "", redo);
462                 REGISTER_CALLBACK (serv, X_("/redo"), "f", redo);
463                 REGISTER_CALLBACK (serv, X_("/toggle_punch_in"), "", toggle_punch_in);
464                 REGISTER_CALLBACK (serv, X_("/toggle_punch_in"), "f", toggle_punch_in);
465                 REGISTER_CALLBACK (serv, X_("/toggle_punch_out"), "", toggle_punch_out);
466                 REGISTER_CALLBACK (serv, X_("/toggle_punch_out"), "f", toggle_punch_out);
467                 REGISTER_CALLBACK (serv, X_("/rec_enable_toggle"), "", rec_enable_toggle);
468                 REGISTER_CALLBACK (serv, X_("/rec_enable_toggle"), "f", rec_enable_toggle);
469                 REGISTER_CALLBACK (serv, X_("/toggle_all_rec_enables"), "", toggle_all_rec_enables);
470                 REGISTER_CALLBACK (serv, X_("/toggle_all_rec_enables"), "f", toggle_all_rec_enables);
471                 REGISTER_CALLBACK (serv, X_("/all_tracks_rec_in"), "f", all_tracks_rec_in);
472                 REGISTER_CALLBACK (serv, X_("/all_tracks_rec_out"), "f", all_tracks_rec_out);
473                 REGISTER_CALLBACK (serv, X_("/cancel_all_solos"), "f", cancel_all_solos);
474                 REGISTER_CALLBACK (serv, X_("/remove_marker"), "", remove_marker_at_playhead);
475                 REGISTER_CALLBACK (serv, X_("/remove_marker"), "f", remove_marker_at_playhead);
476                 REGISTER_CALLBACK (serv, X_("/jump_bars"), "f", jump_by_bars);
477                 REGISTER_CALLBACK (serv, X_("/jump_seconds"), "f", jump_by_seconds);
478                 REGISTER_CALLBACK (serv, X_("/mark_in"), "", mark_in);
479                 REGISTER_CALLBACK (serv, X_("/mark_in"), "f", mark_in);
480                 REGISTER_CALLBACK (serv, X_("/mark_out"), "", mark_out);
481                 REGISTER_CALLBACK (serv, X_("/mark_out"), "f", mark_out);
482                 REGISTER_CALLBACK (serv, X_("/toggle_click"), "", toggle_click);
483                 REGISTER_CALLBACK (serv, X_("/toggle_click"), "f", toggle_click);
484                 REGISTER_CALLBACK (serv, X_("/click/level"), "f", click_level);
485                 REGISTER_CALLBACK (serv, X_("/midi_panic"), "", midi_panic);
486                 REGISTER_CALLBACK (serv, X_("/midi_panic"), "f", midi_panic);
487                 REGISTER_CALLBACK (serv, X_("/toggle_roll"), "", toggle_roll);
488                 REGISTER_CALLBACK (serv, X_("/toggle_roll"), "f", toggle_roll);
489                 REGISTER_CALLBACK (serv, X_("/stop_forget"), "", stop_forget);
490                 REGISTER_CALLBACK (serv, X_("/stop_forget"), "f", stop_forget);
491                 REGISTER_CALLBACK (serv, X_("/set_punch_range"), "", set_punch_range);
492                 REGISTER_CALLBACK (serv, X_("/set_punch_range"), "f", set_punch_range);
493                 REGISTER_CALLBACK (serv, X_("/set_loop_range"), "", set_loop_range);
494                 REGISTER_CALLBACK (serv, X_("/set_loop_range"), "f", set_loop_range);
495                 REGISTER_CALLBACK (serv, X_("/set_session_range"), "", set_session_range);
496                 REGISTER_CALLBACK (serv, X_("/set_session_range"), "f", set_session_range);
497                 REGISTER_CALLBACK (serv, X_("/toggle_monitor_mute"), "", toggle_monitor_mute);
498                 REGISTER_CALLBACK (serv, X_("/toggle_monitor_mute"), "f", toggle_monitor_mute);
499                 REGISTER_CALLBACK (serv, X_("/toggle_monitor_dim"), "", toggle_monitor_dim);
500                 REGISTER_CALLBACK (serv, X_("/toggle_monitor_dim"), "f", toggle_monitor_dim);
501                 REGISTER_CALLBACK (serv, X_("/toggle_monitor_mono"), "", toggle_monitor_mono);
502                 REGISTER_CALLBACK (serv, X_("/toggle_monitor_mono"), "f", toggle_monitor_mono);
503                 REGISTER_CALLBACK (serv, X_("/quick_snapshot_switch"), "", quick_snapshot_switch);
504                 REGISTER_CALLBACK (serv, X_("/quick_snapshot_switch"), "f", quick_snapshot_switch);
505                 REGISTER_CALLBACK (serv, X_("/quick_snapshot_stay"), "", quick_snapshot_stay);
506                 REGISTER_CALLBACK (serv, X_("/quick_snapshot_stay"), "f", quick_snapshot_stay);
507                 REGISTER_CALLBACK (serv, X_("/session_name"), "s", name_session);
508                 REGISTER_CALLBACK (serv, X_("/fit_1_track"), "", fit_1_track);
509                 REGISTER_CALLBACK (serv, X_("/fit_1_track"), "f", fit_1_track);
510                 REGISTER_CALLBACK (serv, X_("/fit_2_tracks"), "", fit_2_tracks);
511                 REGISTER_CALLBACK (serv, X_("/fit_2_tracks"), "f", fit_2_tracks);
512                 REGISTER_CALLBACK (serv, X_("/fit_4_tracks"), "", fit_4_tracks);
513                 REGISTER_CALLBACK (serv, X_("/fit_4_tracks"), "f", fit_4_tracks);
514                 REGISTER_CALLBACK (serv, X_("/fit_8_tracks"), "", fit_8_tracks);
515                 REGISTER_CALLBACK (serv, X_("/fit_8_tracks"), "f", fit_8_tracks);
516                 REGISTER_CALLBACK (serv, X_("/fit_16_tracks"), "", fit_16_tracks);
517                 REGISTER_CALLBACK (serv, X_("/fit_16_tracks"), "f", fit_16_tracks);
518                 REGISTER_CALLBACK (serv, X_("/fit_32_tracks"), "", fit_32_tracks);
519                 REGISTER_CALLBACK (serv, X_("/fit_32_tracks"), "f", fit_32_tracks);
520                 REGISTER_CALLBACK (serv, X_("/fit_all_tracks"), "", fit_all_tracks);
521                 REGISTER_CALLBACK (serv, X_("/fit_all_tracks"), "f", fit_all_tracks);
522                 REGISTER_CALLBACK (serv, X_("/zoom_100_ms"), "", zoom_100_ms);
523                 REGISTER_CALLBACK (serv, X_("/zoom_100_ms"), "f", zoom_100_ms);
524                 REGISTER_CALLBACK (serv, X_("/zoom_1_sec"), "", zoom_1_sec);
525                 REGISTER_CALLBACK (serv, X_("/zoom_1_sec"), "f", zoom_1_sec);
526                 REGISTER_CALLBACK (serv, X_("/zoom_10_sec"), "", zoom_10_sec);
527                 REGISTER_CALLBACK (serv, X_("/zoom_10_sec"), "f", zoom_10_sec);
528                 REGISTER_CALLBACK (serv, X_("/zoom_1_min"), "", zoom_1_min);
529                 REGISTER_CALLBACK (serv, X_("/zoom_1_min"), "f", zoom_1_min);
530                 REGISTER_CALLBACK (serv, X_("/zoom_5_min"), "", zoom_5_min);
531                 REGISTER_CALLBACK (serv, X_("/zoom_5_min"), "f", zoom_5_min);
532                 REGISTER_CALLBACK (serv, X_("/zoom_10_min"), "", zoom_10_min);
533                 REGISTER_CALLBACK (serv, X_("/zoom_10_min"), "f", zoom_10_min);
534                 REGISTER_CALLBACK (serv, X_("/zoom_to_session"), "", zoom_to_session);
535                 REGISTER_CALLBACK (serv, X_("/zoom_to_session"), "f", zoom_to_session);
536                 REGISTER_CALLBACK (serv, X_("/temporal_zoom_in"), "f", temporal_zoom_in);
537                 REGISTER_CALLBACK (serv, X_("/temporal_zoom_in"), "", temporal_zoom_in);
538                 REGISTER_CALLBACK (serv, X_("/temporal_zoom_out"), "", temporal_zoom_out);
539                 REGISTER_CALLBACK (serv, X_("/temporal_zoom_out"), "f", temporal_zoom_out);
540                 REGISTER_CALLBACK (serv, X_("/scroll_up_1_track"), "f", scroll_up_1_track);
541                 REGISTER_CALLBACK (serv, X_("/scroll_up_1_track"), "", scroll_up_1_track);
542                 REGISTER_CALLBACK (serv, X_("/scroll_dn_1_track"), "f", scroll_dn_1_track);
543                 REGISTER_CALLBACK (serv, X_("/scroll_dn_1_track"), "", scroll_dn_1_track);
544                 REGISTER_CALLBACK (serv, X_("/scroll_up_1_page"), "f", scroll_up_1_page);
545                 REGISTER_CALLBACK (serv, X_("/scroll_up_1_page"), "", scroll_up_1_page);
546                 REGISTER_CALLBACK (serv, X_("/scroll_dn_1_page"), "f", scroll_dn_1_page);
547                 REGISTER_CALLBACK (serv, X_("/scroll_dn_1_page"), "", scroll_dn_1_page);
548                 REGISTER_CALLBACK (serv, X_("/bank_up"), "", bank_up);
549                 REGISTER_CALLBACK (serv, X_("/bank_up"), "f", bank_delta);
550                 REGISTER_CALLBACK (serv, X_("/bank_down"), "", bank_down);
551                 REGISTER_CALLBACK (serv, X_("/bank_down"), "f", bank_down);
552                 REGISTER_CALLBACK (serv, X_("/use_group"), "f", use_group);
553
554                 // controls for "special" strips
555                 REGISTER_CALLBACK (serv, X_("/master/gain"), "f", master_set_gain);
556                 REGISTER_CALLBACK (serv, X_("/master/fader"), "f", master_set_fader);
557                 REGISTER_CALLBACK (serv, X_("/master/db_delta"), "f", master_delta_gain);
558                 REGISTER_CALLBACK (serv, X_("/master/mute"), "i", master_set_mute);
559                 REGISTER_CALLBACK (serv, X_("/master/trimdB"), "f", master_set_trim);
560                 REGISTER_CALLBACK (serv, X_("/master/pan_stereo_position"), "f", master_set_pan_stereo_position);
561                 REGISTER_CALLBACK (serv, X_("/master/select"), "f", master_select);
562                 REGISTER_CALLBACK (serv, X_("/monitor/gain"), "f", monitor_set_gain);
563                 REGISTER_CALLBACK (serv, X_("/monitor/fader"), "f", monitor_set_fader);
564                 REGISTER_CALLBACK (serv, X_("/monitor/db_delta"), "f", monitor_delta_gain);
565                 REGISTER_CALLBACK (serv, X_("/monitor/mute"), "i", monitor_set_mute);
566                 REGISTER_CALLBACK (serv, X_("/monitor/dim"), "i", monitor_set_dim);
567                 REGISTER_CALLBACK (serv, X_("/monitor/mono"), "i", monitor_set_mono);
568
569                 // Controls for the Selected strip
570                 REGISTER_CALLBACK (serv, X_("/select/recenable"), "i", sel_recenable);
571                 REGISTER_CALLBACK (serv, X_("/select/record_safe"), "i", sel_recsafe);
572                 REGISTER_CALLBACK (serv, X_("/select/name"), "s", sel_rename);
573                 REGISTER_CALLBACK (serv, X_("/select/comment"), "s", sel_comment);
574                 REGISTER_CALLBACK (serv, X_("/select/mute"), "i", sel_mute);
575                 REGISTER_CALLBACK (serv, X_("/select/solo"), "i", sel_solo);
576                 REGISTER_CALLBACK (serv, X_("/select/solo_iso"), "i", sel_solo_iso);
577                 REGISTER_CALLBACK (serv, X_("/select/solo_safe"), "i", sel_solo_safe);
578                 REGISTER_CALLBACK (serv, X_("/select/monitor_input"), "i", sel_monitor_input);
579                 REGISTER_CALLBACK (serv, X_("/select/monitor_disk"), "i", sel_monitor_disk);
580                 REGISTER_CALLBACK (serv, X_("/select/polarity"), "i", sel_phase);
581                 REGISTER_CALLBACK (serv, X_("/select/gain"), "f", sel_gain);
582                 REGISTER_CALLBACK (serv, X_("/select/fader"), "f", sel_fader);
583                 REGISTER_CALLBACK (serv, X_("/select/db_delta"), "f", sel_dB_delta);
584                 REGISTER_CALLBACK (serv, X_("/select/trimdB"), "f", sel_trim);
585                 REGISTER_CALLBACK (serv, X_("/select/hide"), "i", sel_hide);
586                 REGISTER_CALLBACK (serv, X_("/select/pan_stereo_position"), "f", sel_pan_position);
587                 REGISTER_CALLBACK (serv, X_("/select/pan_stereo_width"), "f", sel_pan_width);
588                 REGISTER_CALLBACK (serv, X_("/select/send_gain"), "if", sel_sendgain);
589                 REGISTER_CALLBACK (serv, X_("/select/send_fader"), "if", sel_sendfader);
590                 REGISTER_CALLBACK (serv, X_("/select/send_enable"), "if", sel_sendenable);
591                 REGISTER_CALLBACK (serv, X_("/select/master_send_enable"), "i", sel_master_send_enable);
592                 REGISTER_CALLBACK (serv, X_("/select/send_page"), "f", sel_send_page);
593                 REGISTER_CALLBACK (serv, X_("/select/plug_page"), "f", sel_plug_page);
594                 REGISTER_CALLBACK (serv, X_("/select/plugin"), "f", sel_plugin);
595                 REGISTER_CALLBACK (serv, X_("/select/plugin/activate"), "f", sel_plugin_activate);
596                 REGISTER_CALLBACK (serv, X_("/select/expand"), "i", sel_expand);
597                 REGISTER_CALLBACK (serv, X_("/select/pan_elevation_position"), "f", sel_pan_elevation);
598                 REGISTER_CALLBACK (serv, X_("/select/pan_frontback_position"), "f", sel_pan_frontback);
599                 REGISTER_CALLBACK (serv, X_("/select/pan_lfe_control"), "f", sel_pan_lfe);
600                 REGISTER_CALLBACK (serv, X_("/select/comp_enable"), "f", sel_comp_enable);
601                 REGISTER_CALLBACK (serv, X_("/select/comp_threshold"), "f", sel_comp_threshold);
602                 REGISTER_CALLBACK (serv, X_("/select/comp_speed"), "f", sel_comp_speed);
603                 REGISTER_CALLBACK (serv, X_("/select/comp_mode"), "f", sel_comp_mode);
604                 REGISTER_CALLBACK (serv, X_("/select/comp_makeup"), "f", sel_comp_makeup);
605                 REGISTER_CALLBACK (serv, X_("/select/eq_enable"), "f", sel_eq_enable);
606                 REGISTER_CALLBACK (serv, X_("/select/eq_hpf/freq"), "f", sel_eq_hpf_freq);
607                 REGISTER_CALLBACK (serv, X_("/select/eq_hpf/enable"), "f", sel_eq_hpf_enable);
608                 REGISTER_CALLBACK (serv, X_("/select/eq_hpf/slope"), "f", sel_eq_hpf_slope);
609                 REGISTER_CALLBACK (serv, X_("/select/eq_lpf/freq"), "f", sel_eq_lpf_freq);
610                 REGISTER_CALLBACK (serv, X_("/select/eq_lpf/enable"), "f", sel_eq_lpf_enable);
611                 REGISTER_CALLBACK (serv, X_("/select/eq_lpf/slope"), "f", sel_eq_lpf_slope);
612                 REGISTER_CALLBACK (serv, X_("/select/eq_gain"), "if", sel_eq_gain);
613                 REGISTER_CALLBACK (serv, X_("/select/eq_freq"), "if", sel_eq_freq);
614                 REGISTER_CALLBACK (serv, X_("/select/eq_q"), "if", sel_eq_q);
615                 REGISTER_CALLBACK (serv, X_("/select/eq_shape"), "if", sel_eq_shape);
616
617                 /* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these  */
618                 REGISTER_CALLBACK (serv, X_("/strip/mute"), "ii", route_mute);
619                 REGISTER_CALLBACK (serv, X_("/strip/solo"), "ii", route_solo);
620                 REGISTER_CALLBACK (serv, X_("/strip/solo_iso"), "ii", route_solo_iso);
621                 REGISTER_CALLBACK (serv, X_("/strip/solo_safe"), "ii", route_solo_safe);
622                 REGISTER_CALLBACK (serv, X_("/strip/recenable"), "ii", route_recenable);
623                 REGISTER_CALLBACK (serv, X_("/strip/record_safe"), "ii", route_recsafe);
624                 REGISTER_CALLBACK (serv, X_("/strip/monitor_input"), "ii", route_monitor_input);
625                 REGISTER_CALLBACK (serv, X_("/strip/monitor_disk"), "ii", route_monitor_disk);
626                 REGISTER_CALLBACK (serv, X_("/strip/expand"), "ii", strip_expand);
627                 REGISTER_CALLBACK (serv, X_("/strip/hide"), "ii", strip_hide);
628                 REGISTER_CALLBACK (serv, X_("/strip/select"), "ii", strip_gui_select);
629                 REGISTER_CALLBACK (serv, X_("/strip/polarity"), "ii", strip_phase);
630                 REGISTER_CALLBACK (serv, X_("/strip/gain"), "if", route_set_gain_dB);
631                 REGISTER_CALLBACK (serv, X_("/strip/fader"), "if", route_set_gain_fader);
632                 REGISTER_CALLBACK (serv, X_("/strip/trimdB"), "if", route_set_trim_dB);
633                 REGISTER_CALLBACK (serv, X_("/strip/pan_stereo_position"), "if", route_set_pan_stereo_position);
634                 REGISTER_CALLBACK (serv, X_("/strip/pan_stereo_width"), "if", route_set_pan_stereo_width);
635                 REGISTER_CALLBACK (serv, X_("/strip/plugin/parameter"), "iiif", route_plugin_parameter);
636                 // prints to cerr only
637                 REGISTER_CALLBACK (serv, X_("/strip/plugin/parameter/print"), "iii", route_plugin_parameter_print);
638                 REGISTER_CALLBACK (serv, X_("/strip/plugin/activate"), "ii", route_plugin_activate);
639                 REGISTER_CALLBACK (serv, X_("/strip/plugin/deactivate"), "ii", route_plugin_deactivate);
640                 REGISTER_CALLBACK (serv, X_("/strip/send/gain"), "iif", route_set_send_gain_dB);
641                 REGISTER_CALLBACK (serv, X_("/strip/send/fader"), "iif", route_set_send_fader);
642                 REGISTER_CALLBACK (serv, X_("/strip/send/enable"), "iif", route_set_send_enable);
643                 REGISTER_CALLBACK (serv, X_("/strip/name"), "is", route_rename);
644                 REGISTER_CALLBACK (serv, X_("/strip/group"), "is", strip_group);
645                 REGISTER_CALLBACK (serv, X_("/strip/sends"), "i", route_get_sends);
646                 REGISTER_CALLBACK (serv, X_("/strip/receives"), "i", route_get_receives);
647                 REGISTER_CALLBACK (serv, X_("/strip/plugin/list"), "i", route_plugin_list);
648                 REGISTER_CALLBACK (serv, X_("/strip/plugin/descriptor"), "ii", route_plugin_descriptor);
649                 REGISTER_CALLBACK (serv, X_("/strip/plugin/reset"), "ii", route_plugin_reset);
650
651                 /* still not-really-standardized query interface */
652                 //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
653                 //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
654
655                 // un/register_update args= s:ctrl s:returl s:retpath
656                 //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
657                 //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
658                 //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
659                 //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
660
661                 /* this is a special catchall handler,
662                  * register at the end so this is only called if no
663                  * other handler matches (also used for debug) */
664                 lo_server_add_method (serv, 0, 0, _catchall, this);
665         }
666 }
667
668 bool
669 OSC::osc_input_handler (IOCondition ioc, lo_server srv)
670 {
671         if (ioc & ~IO_IN) {
672                 return false;
673         }
674
675         if (ioc & IO_IN) {
676                 lo_server_recv (srv);
677         }
678
679         return true;
680 }
681
682 std::string
683 OSC::get_server_url()
684 {
685         string url;
686         char * urlstr;
687
688         if (_osc_server) {
689                 urlstr = lo_server_get_url (_osc_server);
690                 url = urlstr;
691                 free (urlstr);
692         }
693
694         return url;
695 }
696
697 std::string
698 OSC::get_unix_server_url()
699 {
700         string url;
701         char * urlstr;
702
703         if (_osc_unix_server) {
704                 urlstr = lo_server_get_url (_osc_unix_server);
705                 url = urlstr;
706                 free (urlstr);
707         }
708
709         return url;
710 }
711
712 void
713 OSC::gui_changed ()
714 {
715         session->set_dirty();
716 }
717
718 void
719 OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg)
720 {
721         char* subpath;
722
723         subpath = (char*) malloc (len-15+1);
724         memcpy (subpath, path, len-15);
725         subpath[len-15] = '\0';
726
727         send_current_value (subpath, argv, argc, msg);
728
729         free (subpath);
730 }
731
732 void
733 OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg)
734 {
735         if (!session) {
736                 return;
737         }
738
739         lo_message reply = lo_message_new ();
740         boost::shared_ptr<Route> r;
741         int id;
742
743         lo_message_add_string (reply, path);
744
745         if (argc == 0) {
746                 lo_message_add_string (reply, "bad syntax");
747         } else {
748                 id = argv[0]->i;
749                 r = session->get_remote_nth_route (id);
750
751                 if (!r) {
752                         lo_message_add_string (reply, "not found");
753                 } else {
754
755                         if (strcmp (path, X_("/strip/state")) == 0) {
756
757                                 if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
758                                         lo_message_add_string (reply, "AT");
759                                 } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
760                                         lo_message_add_string (reply, "MT");
761                                 } else {
762                                         lo_message_add_string (reply, "B");
763                                 }
764
765                                 lo_message_add_string (reply, r->name().c_str());
766                                 lo_message_add_int32 (reply, r->n_inputs().n_audio());
767                                 lo_message_add_int32 (reply, r->n_outputs().n_audio());
768                                 lo_message_add_int32 (reply, r->muted());
769                                 lo_message_add_int32 (reply, r->soloed());
770
771                         } else if (strcmp (path, X_("/strip/mute")) == 0) {
772
773                                 lo_message_add_int32 (reply, (float) r->muted());
774
775                         } else if (strcmp (path, X_("/strip/solo")) == 0) {
776
777                                 lo_message_add_int32 (reply, r->soloed());
778                         }
779                 }
780         }
781         OSCSurface *sur = get_surface(get_address (msg));
782
783         if (sur->feedback[14]) {
784                 lo_send_message (get_address (msg), X_("/reply"), reply);
785         } else {
786                 lo_send_message (get_address (msg), X_("#reply"), reply);
787         }
788         lo_message_free (reply);
789 }
790
791 int
792 OSC::_catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data)
793 {
794         return ((OSC*)user_data)->catchall (path, types, argv, argc, data);
795 }
796
797 int
798 OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
799 {
800         size_t len;
801         int ret = 1; /* unhandled */
802
803         //cerr << "Received a message, path = " << path << " types = \""
804         //     << (types ? types : "NULL") << '"' << endl;
805
806         /* 15 for /#current_value plus 2 for /<path> */
807
808         len = strlen (path);
809         OSCSurface *sur = get_surface(get_address (msg), true);
810         LinkSet *set;
811         uint32_t ls = sur->linkset;
812
813         if (ls) {
814                 set = &(link_sets[ls]);
815                 sur->custom_mode = set->custom_mode;
816                 sur->custom_strips = set->custom_strips;
817                 sur->temp_strips = set->temp_strips;
818         }
819
820         if (strstr (path, X_("/automation"))) {
821                 ret = set_automation (path, types, argv, argc, msg);
822
823         } else
824         if (strstr (path, X_("/touch"))) {
825                 ret = touch_detect (path, types, argv, argc, msg);
826
827         } else
828         if (len >= 17 && !strcmp (&path[len-15], X_("/#current_value"))) {
829                 current_value_query (path, len, argv, argc, msg);
830                 ret = 0;
831
832         } else
833         if (!strncmp (path, X_("/cue/"), 5)) {
834
835                 ret = cue_parse (path, types, argv, argc, msg);
836
837         } else
838         if (!strncmp (path, X_("/select/plugin/parameter"), 24)) {
839
840                 ret = select_plugin_parameter (path, types, argv, argc, msg);
841
842         } else
843         if (!strncmp (path, X_("/access_action/"), 15)) {
844                 check_surface (msg);
845                 if (!(argc && !argv[0]->i)) {
846                         std::string action_path = path;
847
848                         access_action (action_path.substr(15));
849                 }
850
851                 ret = 0;
852         } else
853         if (strcmp (path, X_("/strip/listen")) == 0) {
854                 if (argc <= 0) {
855                         PBD::warning << "OSC: Wrong number of parameters." << endmsg;
856                 } else if (sur->custom_mode) {
857                         PBD::warning << "OSC: Can't add strips with custom enabled." << endmsg;
858                 } else {
859                         for (int n = 0; n < argc; ++n) {
860                                 boost::shared_ptr<Stripable> s = boost::shared_ptr<Stripable>();
861                                 if (types[n] == 'f') {
862                                         s = get_strip ((uint32_t) argv[n]->f, get_address (msg));
863                                 } else if (types[n] == 'i') {
864                                         s = get_strip (argv[n]->i, get_address (msg));
865                                 }
866                                 if (s) {
867                                         sur->custom_strips.push_back (s);
868                                 }
869                         }
870                         if (ls) {
871                                 set->custom_strips = sur->custom_strips;
872                         }
873                 }
874                 ret = 0;
875         } else
876         if (strcmp (path, X_("/strip/ignore")) == 0) {
877                 if (argc <= 0) {
878                         PBD::warning << "OSC: Wrong number of parameters." << endmsg;
879                 } else if (!sur->custom_mode) {
880                         PBD::warning << "OSC: Can't remove strips without custom enabled." << endmsg;
881                 } else {
882                         for (int n = 0; n < argc; ++n) {
883                                 uint32_t st_no = 0;
884                                 if (types[n] == 'f') {
885                                         st_no = (uint32_t) argv[n]->f;
886                                 } else if (types[n] == 'i') {
887                                         st_no = (uint32_t) argv[n]->i;
888                                 }
889                                 if (st_no && st_no <= sur->custom_strips.size ()) {
890                                         sur->custom_strips[argv[n]->i - 1] = boost::shared_ptr<Stripable>();
891                                 }
892                         }
893                         if (ls) {
894                                 set->custom_strips = sur->custom_strips;
895                         }
896                         ret = set_bank (sur->bank, msg);
897                 }
898
899                 ret = 0;
900         } else
901         if (strstr (path, X_("/strip")) && (argc != 1)) {
902                 // All of the strip commands below require 1 parameter
903                 PBD::warning << "OSC: Wrong number of parameters." << endmsg;
904         } else
905         if (!strncmp (path, X_("/strip/gain/"), 12) && strlen (path) > 12) {
906                 // in dB
907                 int ssid = atoi (&path[12]);
908                 ret = route_set_gain_dB (ssid, argv[0]->f, msg);
909         }
910         else if (!strncmp (path, X_("/strip/fader/"), 13) && strlen (path) > 13) {
911                 // in fader position
912                 int ssid = atoi (&path[13]);
913                 ret = route_set_gain_fader (ssid, argv[0]->f, msg);
914         }
915         else if (!strncmp (path, X_("/strip/db_delta"), 15)) {
916                 // in db delta
917                 int ssid;
918                 int ar_off = 0;
919                 float delta;
920                 if (strlen (path) > 15 && argc == 1) {
921                         ssid = atoi (&path[16]);
922                 } else if (argc == 2) {
923                         if (types[0] == 'f') {
924                                 ssid = (int) argv[0]->f;
925                         } else {
926                                 ssid = argv[0]->i;
927                         }
928                         ar_off = 1;
929                 } else {
930                         return -1;
931                 }
932                 if (types[ar_off] == 'f') {
933                         delta = argv[ar_off]->f;
934                 } else {
935                         delta = (float) argv[ar_off]->i;
936                 }
937                 ret = strip_db_delta (ssid, delta, msg);
938         }
939         else if (!strncmp (path, X_("/strip/trimdB/"), 14) && strlen (path) > 14) {
940                 int ssid = atoi (&path[14]);
941                 ret = route_set_trim_dB (ssid, argv[0]->f, msg);
942         }
943         else if (!strncmp (path, X_("/strip/pan_stereo_position/"), 27) && strlen (path) > 27) {
944                 int ssid = atoi (&path[27]);
945                 ret = route_set_pan_stereo_position (ssid, argv[0]->f, msg);
946         }
947         else if (!strncmp (path, X_("/strip/mute/"), 12) && strlen (path) > 12) {
948                 int ssid = atoi (&path[12]);
949                 ret = route_mute (ssid, argv[0]->i, msg);
950         }
951         else if (!strncmp (path, X_("/strip/solo/"), 12) && strlen (path) > 12) {
952                 int ssid = atoi (&path[12]);
953                 ret = route_solo (ssid, argv[0]->i, msg);
954         }
955         else if (!strncmp (path, X_("/strip/monitor_input/"), 21) && strlen (path) > 21) {
956                 int ssid = atoi (&path[21]);
957                 ret = route_monitor_input (ssid, argv[0]->i, msg);
958         }
959         else if (!strncmp (path, X_("/strip/monitor_disk/"), 20) && strlen (path) > 20) {
960                 int ssid = atoi (&path[20]);
961                 ret = route_monitor_disk (ssid, argv[0]->i, msg);
962         }
963         else if (!strncmp (path, X_("/strip/recenable/"), 17) && strlen (path) > 17) {
964                 int ssid = atoi (&path[17]);
965                 ret = route_recenable (ssid, argv[0]->i, msg);
966         }
967         else if (!strncmp (path, X_("/strip/record_safe/"), 19) && strlen (path) > 19) {
968                 int ssid = atoi (&path[19]);
969                 ret = route_recsafe (ssid, argv[0]->i, msg);
970         }
971         else if (!strncmp (path, X_("/strip/expand/"), 14) && strlen (path) > 14) {
972                 int ssid = atoi (&path[14]);
973                 ret = strip_expand (ssid, argv[0]->i, msg);
974         }
975         else if (!strncmp (path, X_("/strip/hide/"), 12) && strlen (path) > 12) {
976                 int ssid = atoi (&path[12]);
977                 ret = strip_hide (ssid, argv[0]->i, msg);
978         }
979         else if (!strncmp (path, X_("/strip/select/"), 14) && strlen (path) > 14) {
980                 int ssid = atoi (&path[14]);
981                 ret = strip_gui_select (ssid, argv[0]->i, msg);
982         }
983         else if (strstr (path, X_("/select/group"))) {
984                 ret = parse_sel_group (path, types, argv, argc, msg);
985         }
986         else if (strstr (path, X_("/select/vca"))) {
987                 ret = parse_sel_vca (path, types, argv, argc, msg);
988         }
989         else if (strstr (path, X_("/select")) && (argc != 1)) {
990                 // All of the select commands below require 1 parameter
991                 PBD::warning << "OSC: Wrong number of parameters." << endmsg;
992         }
993         else if (!strncmp (path, X_("/select/send_gain/"), 18) && strlen (path) > 18) {
994                 int ssid = atoi (&path[18]);
995                 ret = sel_sendgain (ssid, argv[0]->f, msg);
996         }
997         else if (!strncmp (path, X_("/select/send_fader/"), 19) && strlen (path) > 19) {
998                 int ssid = atoi (&path[19]);
999                 ret = sel_sendfader (ssid, argv[0]->f, msg);
1000         }
1001         else if (!strncmp (path, X_("/select/send_enable/"), 20) && strlen (path) > 20) {
1002                 int ssid = atoi (&path[20]);
1003                 ret = sel_sendenable (ssid, argv[0]->f, msg);
1004         }
1005         else if (!strncmp (path, X_("/select/eq_gain/"), 16) && strlen (path) > 16) {
1006                 int ssid = atoi (&path[16]);
1007                 ret = sel_eq_gain (ssid, argv[0]->f, msg);
1008         }
1009         else if (!strncmp (path, X_("/select/eq_freq/"), 16) && strlen (path) > 16) {
1010                 int ssid = atoi (&path[16]);
1011                 ret = sel_eq_freq (ssid, argv[0]->f , msg);
1012         }
1013         else if (!strncmp (path, X_("/select/eq_q/"), 13) && strlen (path) > 13) {
1014                 int ssid = atoi (&path[13]);
1015                 ret = sel_eq_q (ssid, argv[0]->f, msg);
1016         }
1017         else if (!strncmp (path, X_("/select/eq_shape/"), 17) && strlen (path) > 17) {
1018                 int ssid = atoi (&path[17]);
1019                 ret = sel_eq_shape (ssid, argv[0]->f, msg);
1020         }
1021         else if (!strncmp (path, X_("/marker"), 7)) {
1022                 ret = set_marker (types, argv, argc, msg);
1023         }
1024         else if (!strncmp (path, X_("/set_surface"), 12)) {
1025                 ret = surface_parse (path, types, argv, argc, msg);
1026         }
1027         else if (strstr (path, X_("/link"))) {
1028                 ret = parse_link (path, types, argv, argc, msg);
1029         }
1030         if (ret) {
1031                 check_surface (msg);
1032         }
1033
1034         if ((ret && _debugmode != Off)) {
1035                 debugmsg (_("Unhandled OSC message"), path, types, argv, argc);
1036         } else if (!ret && _debugmode == All) {
1037                 debugmsg (_("OSC"), path, types, argv, argc);
1038         }
1039
1040         return ret;
1041 }
1042
1043 void
1044 OSC::debugmsg (const char *prefix, const char *path, const char* types, lo_arg **argv, int argc)
1045 {
1046         std::stringstream ss;
1047         for (int i = 0; i < argc; ++i) {
1048                 lo_type type = (lo_type)types[i];
1049                         ss << " ";
1050                 switch (type) {
1051                         case LO_INT32:
1052                                 ss << "i:" << argv[i]->i;
1053                                 break;
1054                         case LO_FLOAT:
1055                                 ss << "f:" << argv[i]->f;
1056                                 break;
1057                         case LO_DOUBLE:
1058                                 ss << "d:" << argv[i]->d;
1059                                 break;
1060                         case LO_STRING:
1061                                 ss << "s:" << &argv[i]->s;
1062                                 break;
1063                         case LO_INT64:
1064                                 ss << "h:" << argv[i]->h;
1065                                 break;
1066                         case LO_CHAR:
1067                                 ss << "c:" << argv[i]->s;
1068                                 break;
1069                         case LO_TIMETAG:
1070                                 ss << "<Timetag>";
1071                                 break;
1072                         case LO_BLOB:
1073                                 ss << "<BLOB>";
1074                                 break;
1075                         case LO_TRUE:
1076                                 ss << "#T";
1077                                 break;
1078                         case LO_FALSE:
1079                                 ss << "#F";
1080                                 break;
1081                         case LO_NIL:
1082                                 ss << "NIL";
1083                                 break;
1084                         case LO_INFINITUM:
1085                                 ss << "#inf";
1086                                 break;
1087                         case LO_MIDI:
1088                                 ss << "<MIDI>";
1089                                 break;
1090                         case LO_SYMBOL:
1091                                 ss << "<SYMBOL>";
1092                                 break;
1093                         default:
1094                                 ss << "< ?? >";
1095                                 break;
1096                 }
1097         }
1098         PBD::info << prefix << ": " << path << ss.str() << endmsg;
1099 }
1100
1101 // "Application Hook" Handlers //
1102 void
1103 OSC::session_loaded (Session& s)
1104 {
1105 //      lo_address listener = lo_address_new (NULL, "7770");
1106 //      lo_send (listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str());
1107 }
1108
1109 void
1110 OSC::session_exported (std::string path, std::string name)
1111 {
1112         lo_address listener = lo_address_new (NULL, "7770");
1113         lo_send (listener, X_("/session/exported"), "ss", path.c_str(), name.c_str());
1114         lo_address_free (listener);
1115 }
1116
1117 // end "Application Hook" Handlers //
1118
1119 /* path callbacks */
1120
1121 int
1122 OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, void */*data*/, void* /*user_data*/)
1123 {
1124 #if 0
1125         const char* returl;
1126
1127         if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != s) {
1128                 return 1;
1129         }
1130
1131         const char *returl = argv[1]->s;
1132         lo_address addr = find_or_cache_addr (returl);
1133
1134         const char *retpath = argv[2]->s;
1135
1136
1137         if (strcmp (argv[0]->s, X_("transport_frame")) == 0) {
1138
1139                 if (session) {
1140                         lo_send (addr, retpath, "i", session->transport_sample());
1141                 }
1142
1143         } else if (strcmp (argv[0]->s, X_("transport_speed")) == 0) {
1144
1145                 if (session) {
1146                         lo_send (addr, retpath, "i", session->transport_sample());
1147                 }
1148
1149         } else if (strcmp (argv[0]->s, X_("transport_locked")) == 0) {
1150
1151                 if (session) {
1152                         lo_send (addr, retpath, "i", session->transport_sample());
1153                 }
1154
1155         } else if (strcmp (argv[0]->s, X_("punch_in")) == 0) {
1156
1157                 if (session) {
1158                         lo_send (addr, retpath, "i", session->transport_sample());
1159                 }
1160
1161         } else if (strcmp (argv[0]->s, X_("punch_out")) == 0) {
1162
1163                 if (session) {
1164                         lo_send (addr, retpath, "i", session->transport_sample());
1165                 }
1166
1167         } else if (strcmp (argv[0]->s, X_("rec_enable")) == 0) {
1168
1169                 if (session) {
1170                         lo_send (addr, retpath, "i", session->transport_sample());
1171                 }
1172
1173         } else {
1174
1175                 /* error */
1176         }
1177 #endif
1178         return 0;
1179 }
1180
1181 void
1182 OSC::routes_list (lo_message msg)
1183 {
1184         if (!session) {
1185                 return;
1186         }
1187         OSCSurface *sur = get_surface(get_address (msg), true);
1188
1189         for (int n = 0; n < (int) sur->nstrips; ++n) {
1190
1191                 boost::shared_ptr<Stripable> s = get_strip (n + 1, get_address (msg));
1192
1193                 if (s) {
1194                         // some things need the route
1195                         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
1196
1197                         lo_message reply = lo_message_new ();
1198
1199                         if (boost::dynamic_pointer_cast<AudioTrack>(s)) {
1200                                 lo_message_add_string (reply, "AT");
1201                         } else if (boost::dynamic_pointer_cast<MidiTrack>(s)) {
1202                                 lo_message_add_string (reply, "MT");
1203                         } else if (boost::dynamic_pointer_cast<VCA>(s)) {
1204                                 lo_message_add_string (reply, "V");
1205                         } else if (s->is_master()) {
1206                                 lo_message_add_string (reply, "MA");
1207                         } else if (s->is_monitor()) {
1208                                 lo_message_add_string (reply, "MO");
1209                         } else if (boost::dynamic_pointer_cast<Route>(s) && !boost::dynamic_pointer_cast<Track>(s)) {
1210                                 if (!(s->presentation_info().flags() & PresentationInfo::MidiBus)) {
1211                                         // r->feeds (session->master_out()) may make more sense
1212                                         if (r->direct_feeds_according_to_reality (session->master_out())) {
1213                                                 // this is a bus
1214                                                 lo_message_add_string (reply, "B");
1215                                         } else {
1216                                                 // this is an Aux out
1217                                                 lo_message_add_string (reply, "AX");
1218                                         }
1219                                 } else {
1220                                         lo_message_add_string (reply, "MB");
1221                                 }
1222                         }
1223
1224                         lo_message_add_string (reply, s->name().c_str());
1225                         if (r) {
1226                                 // routes have inputs and outputs
1227                                 lo_message_add_int32 (reply, r->n_inputs().n_audio());
1228                                 lo_message_add_int32 (reply, r->n_outputs().n_audio());
1229                         } else {
1230                                 // non-routes like VCAs don't
1231                                 lo_message_add_int32 (reply, 0);
1232                                 lo_message_add_int32 (reply, 0);
1233                         }
1234                         if (s->mute_control()) {
1235                                 lo_message_add_int32 (reply, s->mute_control()->get_value());
1236                         } else {
1237                                 lo_message_add_int32 (reply, 0);
1238                         }
1239                         if (s->solo_control()) {
1240                                 lo_message_add_int32 (reply, s->solo_control()->get_value());
1241                         } else {
1242                                 lo_message_add_int32 (reply, 0);
1243                         }
1244                         lo_message_add_int32 (reply, n + 1);
1245                         if (s->rec_enable_control()) {
1246                                 lo_message_add_int32 (reply, s->rec_enable_control()->get_value());
1247                         }
1248                         if (sur->feedback[14]) {
1249                                 lo_send_message (get_address (msg), X_("/reply"), reply);
1250                         } else {
1251                                 lo_send_message (get_address (msg), X_("#reply"), reply);
1252                         }
1253                         lo_message_free (reply);
1254                 }
1255         }
1256
1257         // Send end of listing message
1258         lo_message reply = lo_message_new ();
1259
1260         lo_message_add_string (reply, X_("end_route_list"));
1261         lo_message_add_int64 (reply, session->sample_rate());
1262         lo_message_add_int64 (reply, session->current_end_sample());
1263         if (session->monitor_out()) {
1264                 // this session has a monitor section
1265                 lo_message_add_int32 (reply, 1);
1266         } else {
1267                 lo_message_add_int32 (reply, 0);
1268         }
1269
1270         if (sur->feedback[14]) {
1271                 lo_send_message (get_address (msg), X_("/reply"), reply);
1272         } else {
1273                 lo_send_message (get_address (msg), X_("#reply"), reply);
1274         }
1275
1276         lo_message_free (reply);
1277         // send feedback for newly created control surface
1278         strip_feedback (sur, true);
1279         global_feedback (sur);
1280         _strip_select (boost::shared_ptr<ARDOUR::Stripable>(), get_address (msg));
1281
1282 }
1283
1284 void
1285 OSC::surface_list (lo_message msg)
1286 {
1287                 get_surfaces ();
1288 }
1289
1290 void
1291 OSC::get_surfaces ()
1292 {
1293
1294         /* this function is for debugging and prints lots of
1295          * information about what surfaces Ardour knows about and their
1296          * internal parameters. It is best accessed by sending:
1297          * /surface/list from oscsend. This command does not create
1298          * a surface entry.
1299          */
1300
1301         PBD::info << string_compose ("\nList of known Surfaces (%1):\n", _surface.size());
1302
1303         Glib::Threads::Mutex::Lock lm (surfaces_lock);
1304         for (uint32_t it = 0; it < _surface.size(); it++) {
1305                 OSCSurface* sur = &_surface[it];
1306                 char *chost = lo_url_get_hostname (sur->remote_url.c_str());
1307                 string host = chost;
1308                 free (chost);
1309                 string port = get_port (host);
1310                 if (port != "auto") {
1311                         port = "Manual port";
1312                 } else {
1313                         port = "Auto port";
1314                 }
1315                 PBD::info << string_compose ("\n  Surface: %1 - URL: %2  %3\n", it, sur->remote_url, port);
1316                 PBD::info << string_compose ("  Number of strips: %1   Bank size: %2   Current Bank %3\n", sur->nstrips, sur->bank_size, sur->bank);
1317                 PBD::info << string_compose ("  Use Custom: %1   Custom Strips: %2\n", sur->custom_mode, sur->custom_strips.size ());
1318                 bool ug = false;
1319                 if (sur->usegroup == PBD::Controllable::UseGroup) {
1320                         ug = true;
1321                 }
1322                 PBD::info << string_compose ("  Strip Types: %1   Feedback: %2   No_clear flag: %3   Gain mode: %4   Use groups flag %5\n", \
1323                         sur->strip_types.to_ulong(), sur->feedback.to_ulong(), sur->no_clear, sur->gainmode, ug);
1324                 PBD::info << string_compose ("  Using plugin: %1  of  %2 plugins, with %3 params.  Page size: %4  Page: %5\n", \
1325                         sur->plugin_id, sur->plugins.size(), sur->plug_params.size(), sur->plug_page_size, sur->plug_page);
1326                 PBD::info << string_compose ("  Send page size: %1  Page: %2\n", sur->send_page_size, sur->send_page);
1327                 PBD::info << string_compose ("  Expanded flag %1   Track: %2   Jogmode: %3\n", sur->expand_enable, sur->expand, sur->jogmode);
1328                 PBD::info << string_compose ("  Personal monitor flag %1,   Aux master: %2,   Number of sends: %3\n", sur->cue, sur->aux, sur->sends.size());
1329                 PBD::info << string_compose ("  Linkset: %1   Device Id: %2\n", sur->linkset, sur->linkid);
1330         }
1331         PBD::info << string_compose ("\nList of LinkSets (%1):\n", link_sets.size());
1332         std::map<uint32_t, LinkSet>::iterator it;
1333         for (it = link_sets.begin(); it != link_sets.end(); it++) {
1334                 if (!(*it).first) {
1335                         continue;
1336                 }
1337                 uint32_t devices = 0;
1338                 LinkSet* set = &(*it).second;
1339                 if (set->urls.size()) {
1340                         devices = set->urls.size() - 1;
1341                 }
1342                 PBD::info << string_compose ("\n  Linkset %1 has %2 devices and sees %3 strips\n", (*it).first, devices, set->strips.size());
1343                 PBD::info << string_compose ("  Bank size: %1   Current bank: %2   Strip Types: %3\n", set->banksize, set->bank, set->strip_types.to_ulong());
1344                 PBD::info << string_compose ("  Auto bank sizing: %1 Linkset not ready flag: %2\n", set->autobank, set->not_ready);
1345                 PBD::info << string_compose ("  Use Custom: %1 Number of Custom Strips: %2\n", set->custom_mode, set->custom_strips.size ());
1346         }
1347         PBD::info << endmsg;
1348 }
1349
1350 int
1351 OSC::custom_clear (lo_message msg)
1352 {
1353         if (!session) {
1354                 return 0;
1355         }
1356         OSCSurface *sur = get_surface(get_address (msg), true);
1357         sur->custom_mode = 0;
1358         sur->custom_strips.clear ();
1359         sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, false, sur->custom_strips);
1360         sur->nstrips = sur->strips.size();
1361         LinkSet *set;
1362         uint32_t ls = sur->linkset;
1363         if (ls) {
1364                 set = &(link_sets[ls]);
1365                 set->custom_mode = 0;
1366                 set->custom_strips.clear ();
1367                 set->strips = sur->strips;
1368         }
1369         return set_bank (1, msg);
1370 }
1371
1372 int
1373 OSC::custom_mode (float state, lo_message msg)
1374 {
1375         if (!session) {
1376                 return 0;
1377         }
1378         OSCSurface *sur = get_surface(get_address (msg), true);
1379         LinkSet *set;
1380         uint32_t ls = sur->linkset;
1381
1382         if (ls) {
1383                 set = &(link_sets[ls]);
1384                 sur->custom_mode = set->custom_mode;
1385                 sur->custom_strips = set->custom_strips;
1386         }
1387         if (state > 0){
1388                 if (sur->custom_strips.size () == 0) {
1389                         PBD::warning << "No custom strips set to enable" << endmsg;
1390                         sur->custom_mode = 0;
1391                         if (ls) {
1392                                 set->custom_mode = 0;
1393                         }
1394                         return -1;
1395                 } else {
1396                         if (sur->bank_size) {
1397                                 sur->custom_mode = (uint32_t) state | 0x4;
1398                         } else {
1399                                 sur->custom_mode = (uint32_t) state;
1400                         }
1401                         sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, sur->custom_mode, sur->custom_strips);
1402                         sur->nstrips = sur->custom_strips.size();
1403                 }
1404         } else {
1405                 sur->custom_mode = 0;
1406                 sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, 0, sur->custom_strips);
1407                 sur->nstrips = sur->strips.size();
1408         }
1409         if (ls) {
1410                 set->custom_mode = sur->custom_mode;
1411                 set->strips = sur->strips;
1412         }
1413         return set_bank (1, msg);
1414 }
1415
1416 int
1417 OSC::cancel_all_solos ()
1418 {
1419         session->cancel_all_solo ();
1420         return 0;
1421 }
1422
1423 lo_address
1424 OSC::get_address (lo_message msg)
1425 {
1426         lo_address addr = lo_message_get_source (msg);
1427         string host = lo_address_get_hostname (addr);
1428         string port = lo_address_get_port (addr);
1429         int protocol = lo_address_get_protocol (addr);
1430         string saved_port = get_port (host);
1431         if (saved_port != "") {
1432                 if (saved_port != "auto") {
1433                         port = saved_port;
1434                         return lo_address_new_with_proto (protocol, host.c_str(), port.c_str());
1435                 } else {
1436                         return lo_message_get_source (msg);
1437                 }
1438         }
1439
1440         // if we get here we need to add a new entry for this surface
1441         PortAdd new_port;
1442         new_port.host = host;
1443         if (address_only) {
1444                 new_port.port = remote_port;
1445                 _ports.push_back (new_port);
1446                 return lo_address_new_with_proto (protocol, host.c_str(), remote_port.c_str());
1447         } else {
1448                 new_port.port = "auto";
1449                 _ports.push_back (new_port);
1450                 return lo_message_get_source (msg);
1451         }
1452 }
1453
1454 string
1455 OSC::get_port (string host)
1456 {
1457         for (uint32_t i = 0; i < _ports.size (); i++) {
1458                 if (_ports[i].host == host) {
1459                         return _ports[i].port;
1460                 }
1461         }
1462         return "";
1463 }
1464
1465 int
1466 OSC::refresh_surface (lo_message msg)
1467 {
1468         OSCSurface *s = get_surface(get_address (msg), true);
1469         uint32_t bs = s->bank_size;
1470         uint32_t st = (uint32_t) s->strip_types.to_ulong();
1471         uint32_t fb = (uint32_t) s->feedback.to_ulong();
1472         uint32_t gm = (uint32_t) s->gainmode;
1473         uint32_t sp = s->send_page_size;
1474         uint32_t pp = s->plug_page_size;
1475
1476         surface_destroy (s);
1477         // restart all observers
1478         set_surface (bs, st, fb, gm, sp, pp, msg);
1479         return 0;
1480 }
1481
1482 void
1483 OSC::clear_devices ()
1484 {
1485         tick = false;
1486         observer_busy = true;
1487         session_connections.drop_connections ();
1488         // clear out surfaces
1489         for (uint32_t it = 0; it < _surface.size(); ++it) {
1490                 OSCSurface* sur = &_surface[it];
1491                 surface_destroy (sur);
1492         }
1493         _surface.clear();
1494         link_sets.clear ();
1495         _ports.clear ();
1496
1497         PresentationInfo::Change.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
1498
1499         observer_busy = false;
1500         tick = true;
1501 }
1502
1503 int
1504 OSC::parse_link (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
1505 {
1506         int ret = 1; /* unhandled */
1507         int set = 0;
1508         if (!argc) {
1509                 PBD::warning << "OSC: /link/* needs at least one parameter" << endmsg;
1510                 return ret;
1511         }
1512         float data = 0;
1513         if (types[argc - 1] == 'f') {
1514                 data = argv[argc - 1]->f;
1515         } else {
1516                 data = argv[argc - 1]->i;
1517         }
1518         if (isdigit(strrchr (path, '/')[1])) {
1519                 set = atoi (&(strrchr (path, '/')[1]));
1520         } else if (argc == 2) {
1521                 if (types[0] == 'f') {
1522                         set = (int) argv[0]->f;
1523                 } else {
1524                         set = argv[0]->i;
1525                 }
1526         } else {
1527                 PBD::warning << "OSC: wrong number of parameters." << endmsg;
1528                 return ret;
1529         }
1530         LinkSet *ls = get_linkset (set, get_address (msg));
1531
1532         if (!set) {
1533                 return 0;
1534         }
1535         if (!strncmp (path, X_("/link/bank_size"), 15)) {
1536                 ls->banksize = (uint32_t) data;
1537                 ls->autobank = false;
1538                 ls->not_ready = link_check (set);
1539                 if (ls->not_ready) {
1540                         ls->bank = 1;
1541                         surface_link_state (ls);
1542                 } else {
1543                         _set_bank (ls->bank, get_address (msg));
1544                 }
1545                 ret = 0;
1546
1547         } else if (!strncmp (path, X_("/link/set"), 9)) {
1548                 ret = set_link (set, (uint32_t) data, get_address (msg));
1549         }
1550
1551         return ret;
1552 }
1553
1554 OSC::LinkSet *
1555 OSC::get_linkset (uint32_t set, lo_address addr)
1556 {
1557         OSCSurface *sur = get_surface(addr);
1558         LinkSet *ls = 0;
1559
1560         if (set) {
1561                 // need to check if set is wanted
1562                 std::map<uint32_t, LinkSet>::iterator it;
1563                 it = link_sets.find(set);
1564                 if (it == link_sets.end()) {
1565                         // no such linkset make it
1566                         LinkSet new_ls;
1567                         new_ls.banksize = 0;
1568                         new_ls.bank = 1;
1569                         new_ls.autobank = true;
1570                         new_ls.not_ready = true;
1571                         new_ls.strip_types = sur->strip_types;
1572                         new_ls.strips = sur->strips;
1573                         new_ls.custom_strips = sur->custom_strips;
1574                         new_ls.custom_mode = sur->custom_mode;
1575                         new_ls.urls.resize (2);
1576                         link_sets[set] = new_ls;
1577                 }
1578                 ls = &link_sets[set];
1579
1580         } else {
1581                 // User expects this surface to be removed from any sets
1582                 uint32_t oldset = sur->linkset;
1583                 if (oldset) {
1584                         uint32_t oldid = sur->linkid;
1585                         sur->linkid = 1;
1586                         sur->linkset = 0;
1587                         LinkSet *ols = &link_sets[oldset];
1588                         if (ols) {
1589                                 ols->not_ready = oldid;
1590                                 ols->urls[oldid] = "";
1591                                 surface_link_state (ols);
1592                         }
1593                 }
1594         }
1595         return ls;
1596 }
1597
1598 int
1599 OSC::set_link (uint32_t set, uint32_t id, lo_address addr)
1600 {
1601         OSCSurface *sur = get_surface(addr, true);
1602         sur->linkset = set;
1603         sur->linkid = id;
1604         LinkSet *ls = get_linkset (set, addr);
1605         if (ls->urls.size() <= (uint32_t) id) {
1606                 ls->urls.resize ((int) id + 1);
1607         }
1608         ls->urls[(uint32_t) id] = sur->remote_url;
1609         ls->not_ready = link_check (set);
1610         if (ls->not_ready) {
1611                 surface_link_state (ls);
1612         } else {
1613                 _set_bank (1, addr);
1614         }
1615         return 0;
1616 }
1617
1618 void
1619 OSC::link_strip_types (uint32_t linkset, uint32_t striptypes)
1620 {
1621         LinkSet *ls = 0;
1622
1623         if (!linkset) {
1624                 return;
1625         }
1626         std::map<uint32_t, LinkSet>::iterator it;
1627         it = link_sets.find(linkset);
1628         if (it == link_sets.end()) {
1629                 // this should never happen... but
1630                 return;
1631         }
1632         ls = &link_sets[linkset];
1633         ls->strip_types = striptypes;
1634         for (uint32_t dv = 1; dv < ls->urls.size(); dv++) {
1635                 OSCSurface *su;
1636
1637                 if (ls->urls[dv] != "") {
1638                         string url = ls->urls[dv];
1639                         su = get_surface (lo_address_new_from_url (url.c_str()), true);
1640                         if (su->linkset == linkset) {
1641                                 su->strip_types = striptypes;
1642                                 if (su->strip_types[10]) {
1643                                         su->usegroup = PBD::Controllable::UseGroup;
1644                                 } else {
1645                                         su->usegroup = PBD::Controllable::NoGroup;
1646                                 }
1647                         } else {
1648                                 ls->urls[dv] = "";
1649                         }
1650                 }
1651         }
1652 }
1653
1654 void
1655 OSC::surface_link_state (LinkSet * set)
1656 {
1657         for (uint32_t dv = 1; dv < set->urls.size(); dv++) {
1658
1659                 if (set->urls[dv] != "") {
1660                         string url = set->urls[dv];
1661                         OSCSurface *sur = get_surface (lo_address_new_from_url (url.c_str()), true);
1662                         for (uint32_t i = 0; i < sur->observers.size(); i++) {
1663                                 sur->observers[i]->set_link_ready (set->not_ready);
1664                         }
1665                 }
1666         }
1667 }
1668
1669 int
1670 OSC::link_check (uint32_t set)
1671 {
1672         LinkSet *ls = 0;
1673
1674         if (!set) {
1675                 return 1;
1676         }
1677         std::map<uint32_t, LinkSet>::iterator it;
1678         it = link_sets.find(set);
1679         if (it == link_sets.end()) {
1680                 // this should never happen... but
1681                 return 1;
1682         }
1683         ls = &link_sets[set];
1684         uint32_t bank_total = 0;
1685         for (uint32_t dv = 1; dv < ls->urls.size(); dv++) {
1686                 OSCSurface *su;
1687
1688                 if (ls->urls[dv] != "") {
1689                         string url = ls->urls[dv];
1690                         su = get_surface (lo_address_new_from_url (url.c_str()), true);
1691                 } else {
1692                         return dv;
1693                 }
1694                 if (su->linkset == set) {
1695                         bank_total = bank_total + su->bank_size;
1696                 } else {
1697                         ls->urls[dv] = "";
1698                         return dv;
1699                 }
1700                 if (ls->autobank) {
1701                         ls->banksize = bank_total;
1702                 } else {
1703                         if (bank_total != ls->banksize) {
1704                                 return ls->urls.size();
1705                         }
1706                 }
1707         }
1708         return 0;
1709 }
1710
1711 int
1712 OSC::surface_parse (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
1713 {
1714         int ret = 1; /* unhandled */
1715         OSCSurface *sur = get_surface(get_address (msg), true);
1716         int pi_page = sur->plug_page_size;
1717         int se_page = sur->send_page_size;
1718         int fadermode = sur->gainmode;
1719         int feedback = sur->feedback.to_ulong();
1720         int strip_types = sur->strip_types.to_ulong();
1721         int bank_size = sur->bank_size;
1722         int linkset = sur->linkset;
1723         int linkid = sur->linkid;
1724         string host = lo_url_get_hostname(sur->remote_url.c_str());
1725         int port = atoi (get_port (host).c_str());
1726
1727         if (argc == 1 && !strncmp (path, X_("/set_surface/feedback"), 21)) {
1728                 if (types[0] == 'f') {
1729                         ret = set_surface_feedback ((int)argv[0]->f, msg);
1730                 } else {
1731                         ret = set_surface_feedback (argv[0]->i, msg);
1732                 }
1733         }
1734         else if (argc == 1 && !strncmp (path, X_("/set_surface/bank_size"), 22)) {
1735                 if (types[0] == 'f') {
1736                         ret = set_surface_bank_size ((int)argv[0]->f, msg);
1737                 } else {
1738                         ret = set_surface_bank_size (argv[0]->i, msg);
1739                 }
1740         }
1741         else if (argc == 1 && !strncmp (path, X_("/set_surface/gainmode"), 21)) {
1742                 if (types[0] == 'f') {
1743                         ret = set_surface_gainmode ((int)argv[0]->f, msg);
1744                 } else {
1745                         ret = set_surface_gainmode (argv[0]->i, msg);
1746                 }
1747         }
1748         else if (argc == 1 && !strncmp (path, X_("/set_surface/strip_types"), 24)) {
1749                 if (types[0] == 'f') {
1750                         ret = set_surface_strip_types ((int)argv[0]->f, msg);
1751                 } else {
1752                         ret = set_surface_strip_types (argv[0]->i, msg);
1753                 }
1754         }
1755         else if (argc == 1 && !strncmp (path, X_("/set_surface/send_page_size"), 27)) {
1756                 if (types[0] == 'f') {
1757                         ret = sel_send_pagesize ((int)argv[0]->f, msg);
1758                 } else {
1759                         ret = sel_send_pagesize (argv[0]->i, msg);
1760                 }
1761         }
1762         else if (argc == 1 && !strncmp (path, X_("/set_surface/plugin_page_size"), 29)) {
1763                 if (types[0] == 'f') {
1764                         ret = sel_plug_pagesize ((int)argv[0]->f, msg);
1765                 } else {
1766                         ret = sel_plug_pagesize (argv[0]->i, msg);
1767                 }
1768         }
1769         else if (argc == 1 && !strncmp (path, X_("/set_surface/port"), 17)) {
1770                 if (types[0] == 'f') {
1771                         ret = set_surface_port ((int)argv[0]->f, msg);
1772                 } else {
1773                         ret = set_surface_port (argv[0]->i, msg);
1774                 }
1775         } else if (strlen(path) == 12) {
1776
1777                 // command is in /set_surface iii form
1778                 switch (argc) {
1779                         case 9:
1780                                 if (types[8] == 'f') {
1781                                         linkid = (int) argv[8]->f;
1782                                 } else {
1783                                         linkid = argv[8]->i;
1784                                 }
1785                         case 8:
1786                                 if (types[7] == 'f') {
1787                                         linkset = (int) argv[7]->f;
1788                                 } else {
1789                                         linkset = argv[7]->i;
1790                                 }
1791                         case 7:
1792                                 if (types[6] == 'f') {
1793                                         port = (int) argv[6]->f;
1794                                 } else {
1795                                         port = argv[6]->i;
1796                                 }
1797                         case 6:
1798                                 if (types[5] == 'f') {
1799                                         pi_page = (int) argv[5]->f;
1800                                 } else {
1801                                         pi_page = argv[5]->i;
1802                                 }
1803                         case 5:
1804                                 if (types[4] == 'f') {
1805                                         se_page = (int) argv[4]->f;
1806                                 } else {
1807                                         se_page = argv[4]->i;
1808                                 }
1809                         case 4:
1810                                 if (types[3] == 'f') {
1811                                         fadermode = (int) argv[3]->f;
1812                                 } else {
1813                                         fadermode = argv[3]->i;
1814                                 }
1815                         case 3:
1816                                 if (types[2] == 'f') {
1817                                         feedback = (int) argv[2]->f;
1818                                 } else {
1819                                         feedback = argv[2]->i;
1820                                 }
1821                         case 2:
1822                                 if (types[1] == 'f') {
1823                                         strip_types = (int) argv[1]->f;
1824                                 } else {
1825                                         strip_types = argv[1]->i;
1826                                 }
1827                         case 1:
1828                                 if (types[0] == 'f') {
1829                                         bank_size = (int) argv[0]->f;
1830                                 } else {
1831                                         bank_size = argv[0]->i;
1832                                 }
1833                                 set_surface_port (port, msg);
1834                                 ret = set_surface (bank_size, strip_types, feedback, fadermode, se_page, pi_page, msg);
1835                                 if ((uint32_t) linkset != sur->linkset) {
1836                                         set_link (linkset, linkid, get_address (msg));
1837                                 }
1838                                 break;
1839                         case 0:
1840                                 // send current setup
1841                                 {
1842                                         lo_message reply = lo_message_new ();
1843                                         lo_message_add_int32 (reply, bank_size);
1844                                         lo_message_add_int32 (reply, strip_types);
1845                                         lo_message_add_int32 (reply, feedback);
1846                                         lo_message_add_int32 (reply, fadermode);
1847                                         lo_message_add_int32 (reply, se_page);
1848                                         lo_message_add_int32 (reply, pi_page);
1849                                         lo_message_add_int32 (reply, (int) linkset);
1850                                         lo_message_add_int32 (reply, (int) linkid);
1851                                         lo_message_add_int32 (reply, (int) port);
1852                                         lo_send_message (get_address (msg), X_("/set_surface"), reply);
1853                                         lo_message_free (reply);
1854                                         return 0;
1855                                 }
1856                                 break;
1857
1858                         default:
1859                                 PBD::warning << "OSC: Too many parameters." << endmsg;
1860                                 return 1;
1861                                 break;
1862                 }
1863         } else if (isdigit(path[13])) {
1864                 // some of our parameters must be "in-lined"
1865                 bank_size = atoi (&path[13]);
1866                 const char * par = strstr (&path[13], "/");
1867                 if (par) {
1868                         strip_types = atoi (&par[1]);
1869                         const char * fb = strstr (&par[1], "/");
1870                         if (fb) {
1871                                 feedback = atoi (&fb[1]);
1872                                 const char * fm = strstr (&fb[1], "/");
1873                                 if (fm) {
1874                                         fadermode = atoi (&fm[1]);
1875                                         const char * sp = strstr (&fm[1], "/");
1876                                         if (sp) {
1877                                                 se_page = atoi (&sp[1]);
1878                                                 const char * pp = strstr (&sp[1], "/");
1879                                                 if (pp) {
1880                                                         pi_page = atoi (&pp[1]);
1881                                                         const char * po = strstr (&pp[1], "/");
1882                                                         if (po) {
1883                                                                 port = atoi (&po[1]);
1884                                                                 const char * ls = strstr (&po[1], "/");
1885                                                                 if (ls) {
1886                                                                         linkset = atoi (&ls[1]);
1887                                                                         const char * li = strstr (&ls[1], "/");
1888                                                                         if (li) {
1889                                                                                 linkid = atoi (&li[1]);
1890                                                                         } else {
1891                                                                                 if (types[0] == 'f') {
1892                                                                                         linkid = (int) argv[0]->f;
1893                                                                                 } else if (types[0] == 'i') {
1894                                                                                         linkid = argv[0]->i;
1895                                                                                 }
1896                                                                         }
1897                                                                 } else {
1898                                                                         if (types[0] == 'f') {
1899                                                                                 linkset = (int) argv[0]->f;
1900                                                                         } else if (types[0] == 'i') {
1901                                                                                 linkset = argv[0]->i;
1902                                                                         }
1903                                                                 }
1904                                                         } else {
1905                                                                 if (types[0] == 'f') {
1906                                                                         port = (int) argv[0]->f;
1907                                                                 } else if (types[0] == 'i') {
1908                                                                         port = argv[0]->i;
1909                                                                 }
1910                                                         }
1911                                                 } else {
1912                                                         if (types[0] == 'f') {
1913                                                                 pi_page = (int) argv[0]->f;
1914                                                         } else if (types[0] == 'i') {
1915                                                                 pi_page = argv[0]->i;
1916                                                         }
1917                                                 }
1918                                         } else {
1919                                                 if (types[0] == 'f') {
1920                                                         se_page = (int) argv[0]->f;
1921                                                 } else if (types[0] == 'i') {
1922                                                         se_page = argv[0]->i;
1923                                                 }
1924                                         }
1925                                 } else {
1926                                         if (types[0] == 'f') {
1927                                                 fadermode = (int) argv[0]->f;
1928                                         } else if (types[0] == 'i') {
1929                                                 fadermode = argv[0]->i;
1930                                         }
1931                                 }
1932                         } else {
1933                                 if (types[0] == 'f') {
1934                                         feedback = (int) argv[0]->f;
1935                                 } else if (types[0] == 'i') {
1936                                         feedback = argv[0]->i;
1937                                 }
1938                         }
1939                 } else {
1940                         if (types[0] == 'f') {
1941                                 strip_types = (int) argv[0]->f;
1942                         } else if (types[0] == 'i') {
1943                                 strip_types = argv[0]->i;
1944                         }
1945                 }
1946                 set_surface_port (port, msg);
1947                 ret = set_surface (bank_size, strip_types, feedback, fadermode, se_page, pi_page, msg);
1948                 if ((uint32_t) linkset != sur->linkset) {
1949                         set_link (linkset, linkid, get_address (msg));
1950                 }
1951         }
1952         return ret;
1953 }
1954
1955 int
1956 OSC::set_surface (uint32_t b_size, uint32_t strips, uint32_t fb, uint32_t gm, uint32_t se_size, uint32_t pi_size, lo_message msg)
1957 {
1958         if (observer_busy) {
1959                 return -1;
1960         }
1961         OSCSurface *s = get_surface(get_address (msg), true);
1962         s->bank_size = b_size;
1963         s->custom_mode = 0;
1964         s->strip_types = strips;
1965         s->feedback = fb;
1966         s->gainmode = gm;
1967         if (s->strip_types[10]) {
1968                 s->usegroup = PBD::Controllable::UseGroup;
1969         } else {
1970                 s->usegroup = PBD::Controllable::NoGroup;
1971         }
1972         s->send_page_size = se_size;
1973         s->plug_page_size = pi_size;
1974         if (s->linkset) {
1975                 set_link (s->linkset, s->linkid, get_address (msg));
1976                 link_strip_types (s->linkset, s->strip_types.to_ulong());
1977         } else {
1978                 // set bank and strip feedback
1979                 strip_feedback(s, true);
1980                 _set_bank (1, get_address (msg));
1981         }
1982
1983         global_feedback (s);
1984         sel_send_pagesize (se_size, msg);
1985         sel_plug_pagesize (pi_size, msg);
1986         return 0;
1987 }
1988
1989 int
1990 OSC::set_surface_bank_size (uint32_t bs, lo_message msg)
1991 {
1992         if (observer_busy) {
1993                 return -1;
1994         }
1995         OSCSurface *s = get_surface(get_address (msg), true);
1996         s->bank_size = bs;
1997         if (s->custom_mode && bs) {
1998                 s->custom_mode = s->custom_mode | 0x4;
1999         }
2000         if (s->linkset) {
2001                 set_link (s->linkset, s->linkid, get_address (msg));
2002         } else {
2003                 // set bank and strip feedback
2004                 _set_bank (1, get_address (msg));
2005         }
2006         return 0;
2007 }
2008
2009 int
2010 OSC::set_surface_strip_types (uint32_t st, lo_message msg)
2011 {
2012         if (observer_busy) {
2013                 return -1;
2014         }
2015         OSCSurface *s = get_surface(get_address (msg), true);
2016         s->strip_types = st;
2017         s->custom_mode = 0;
2018         if (s->strip_types[10]) {
2019                 s->usegroup = PBD::Controllable::UseGroup;
2020         } else {
2021                 s->usegroup = PBD::Controllable::NoGroup;
2022         }
2023         if (s->linkset) {
2024                 link_strip_types (s->linkset, st);
2025         }
2026
2027         // set bank and strip feedback
2028         _set_bank (1, get_address (msg));
2029         return 0;
2030 }
2031
2032
2033 int
2034 OSC::set_surface_feedback (uint32_t fb, lo_message msg)
2035 {
2036         if (observer_busy) {
2037                 return -1;
2038         }
2039         OSCSurface *s = get_surface(get_address (msg), true);
2040         s->feedback = fb;
2041
2042         strip_feedback (s, true);
2043         global_feedback (s);
2044         _strip_select (boost::shared_ptr<ARDOUR::Stripable>(), get_address (msg));
2045         return 0;
2046 }
2047
2048 int
2049 OSC::set_surface_gainmode (uint32_t gm, lo_message msg)
2050 {
2051         if (observer_busy) {
2052                 return -1;
2053         }
2054         OSCSurface *s = get_surface(get_address (msg), true);
2055         s->gainmode = gm;
2056
2057         strip_feedback (s, true);
2058         global_feedback (s);
2059         _strip_select (boost::shared_ptr<ARDOUR::Stripable>(), get_address (msg));
2060         return 0;
2061 }
2062
2063 int
2064 OSC::set_surface_port (uint32_t po, lo_message msg)
2065 {
2066         string new_port;
2067         if (!po) {
2068                 new_port = "auto";
2069         } else if (po > 1024) {
2070                 new_port = string_compose ("%1", po);
2071         } else {
2072                 PBD::warning << "Port value must be greater than 1024" << endmsg;
2073                 return -1;
2074         }
2075         OSCSurface *sur = get_surface(get_address (msg), true);
2076         lo_address addr = lo_message_get_source (msg);
2077         string host = lo_address_get_hostname (addr);
2078         string port = lo_address_get_port (addr);
2079         int protocol = lo_address_get_protocol (addr);
2080         for (uint32_t i = 0; i < _ports.size (); i++) {
2081                 if (_ports[i].host == host) {
2082                         if (_ports[i].port == new_port) {
2083                                 // no change - do nothing
2084                                 return 0;
2085                         } else {
2086                                 lo_address new_addr;
2087                                 _ports[i].port = new_port;
2088                                 if (new_port == "auto") {
2089                                         new_addr = addr;
2090                                 } else {
2091                                         new_addr = lo_address_new_with_proto (protocol, host.c_str(), new_port.c_str());
2092                                 }
2093                                 char * rurl;
2094                                 rurl = lo_address_get_url (new_addr);
2095                                 sur->remote_url = rurl;
2096                                 free (rurl);
2097                                 for (uint32_t it = 0; it < _surface.size();) {
2098                                         if (&_surface[it] == sur) {
2099                                                 it++;
2100                                                 continue;
2101                                         }
2102                                         char *sur_host = lo_url_get_hostname(_surface[it].remote_url.c_str());
2103                                         if (strstr (sur_host, host.c_str())) {
2104                                                 surface_destroy (&_surface[it]);
2105                                                 _surface.erase (_surface.begin() + it);
2106                                         } else {
2107                                                 it++;
2108                                         }
2109                                 }
2110                                 refresh_surface (msg);
2111                                 return 0;
2112                         }
2113                 }
2114         }
2115         // should not get here
2116         return -1;
2117 }
2118
2119 int
2120 OSC::check_surface (lo_message msg)
2121 {
2122         if (!session) {
2123                 return -1;
2124         }
2125         get_surface(get_address (msg));
2126         return 0;
2127 }
2128
2129 OSC::OSCSurface *
2130 OSC::get_surface (lo_address addr , bool quiet)
2131 {
2132         string r_url;
2133         char * rurl;
2134         rurl = lo_address_get_url (addr);
2135         r_url = rurl;
2136         free (rurl);
2137         for (uint32_t it = 0; it < _surface.size(); ++it) {
2138                 //find setup for this surface
2139                 if (!_surface[it].remote_url.find(r_url)){
2140                         return &_surface[it];
2141                 }
2142         }
2143
2144         // No surface create one with default values
2145         OSCSurface s;
2146         s.remote_url = r_url;
2147         s.no_clear = false;
2148         s.jogmode = 0;
2149         s.bank = 1;
2150         s.bank_size = default_banksize;
2151         s.observers.clear();
2152         s.sel_obs = 0;
2153         s.global_obs = 0;
2154         s.strip_types = default_strip;
2155         s.feedback = default_feedback;
2156         s.gainmode = default_gainmode;
2157         s.usegroup = PBD::Controllable::NoGroup;
2158         s.custom_strips.clear ();
2159         s.custom_mode = 0;
2160         s.sel_obs = 0;
2161         s.expand = 0;
2162         s.expand_enable = false;
2163         s.cue = false;
2164         s.aux = 0;
2165         s.cue_obs = 0;
2166         s.strips = get_sorted_stripables(s.strip_types, s.cue, false, s.custom_strips);
2167         s.send_page = 1;
2168         s.send_page_size = default_send_size;
2169         s.plug_page = 1;
2170         s.plug_page_size = default_plugin_size;
2171         s.plugin_id = 1;
2172         s.linkset = 0;
2173         s.linkid = 1;
2174
2175         s.nstrips = s.strips.size();
2176         {
2177                 _surface.push_back (s);
2178         }
2179
2180         if (!quiet) {
2181                 strip_feedback (&s, true);
2182                 global_feedback (&s);
2183                 _strip_select (boost::shared_ptr<ARDOUR::Stripable>(), addr);
2184         }
2185
2186         return &_surface[_surface.size() - 1];
2187 }
2188
2189 // setup global feedback for a surface
2190 void
2191 OSC::global_feedback (OSCSurface* sur)
2192 {
2193         OSCGlobalObserver* o = sur->global_obs;
2194         delete o;
2195         if (sur->feedback[4] || sur->feedback[3] || sur->feedback[5] || sur->feedback[6]) {
2196
2197                 // create a new Global Observer for this surface
2198                 OSCGlobalObserver* o = new OSCGlobalObserver (*this, *session, sur);
2199                 sur->global_obs = o;
2200                 o->jog_mode (sur->jogmode);
2201         }
2202 }
2203
2204 void
2205 OSC::strip_feedback (OSCSurface* sur, bool new_bank_size)
2206 {
2207         LinkSet *set;
2208         uint32_t ls = sur->linkset;
2209
2210         if (ls) {
2211                 set = &(link_sets[ls]);
2212                 if (set->not_ready) {
2213                         return;
2214                 }
2215                 sur->custom_mode = set->custom_mode;
2216                 sur->custom_strips = set->custom_strips;
2217                 sur->temp_strips = set->temp_strips;
2218         }
2219         if (sur->custom_mode < 7) {
2220                 sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, sur->custom_mode, sur->custom_strips);
2221         } else {
2222                 sur->strips = get_sorted_stripables(sur->strip_types, sur->cue, 1, sur->temp_strips);
2223         }
2224         sur->nstrips = sur->strips.size();
2225         if (ls) {
2226                 set->strips = sur->strips;
2227         }
2228
2229         if (new_bank_size || (!sur->feedback[0] && !sur->feedback[1])) {
2230                 // delete old observers
2231                 for (uint32_t i = 0; i < sur->observers.size(); i++) {
2232                         if (!sur->bank_size) {
2233                                 sur->observers[i]->clear_strip ();
2234                         }
2235                         delete sur->observers[i];
2236                 }
2237                 sur->observers.clear();
2238
2239                 uint32_t bank_size = sur->bank_size;
2240                 if (!bank_size) {
2241                         bank_size = sur->nstrips;
2242                 }
2243
2244                 if (sur->feedback[0] || sur->feedback[1]) {
2245                         for (uint32_t i = 0; i < bank_size; i++) {
2246                                 OSCRouteObserver* o = new OSCRouteObserver (*this, i + 1, sur);
2247                                 sur->observers.push_back (o);
2248                         }
2249                 }
2250         } else {
2251                 if (sur->feedback[0] || sur->feedback[1]) {
2252                         for (uint32_t i = 0; i < sur->observers.size(); i++) {
2253                                 boost::shared_ptr<ARDOUR::Stripable> str = get_strip (i + 1, lo_address_new_from_url (sur->remote_url.c_str()));
2254                                 sur->observers[i]->refresh_strip(str, true);
2255                         }
2256                 }
2257         }
2258         bank_leds (sur);
2259 }
2260
2261 void
2262 OSC::notify_routes_added (ARDOUR::RouteList &)
2263 {
2264         // not sure if we need this PI change seems to cover
2265         //recalcbanks();
2266 }
2267
2268 void
2269 OSC::notify_vca_added (ARDOUR::VCAList &)
2270 {
2271         // not sure if we need this PI change seems to cover
2272         //recalcbanks();
2273 }
2274
2275 void
2276 OSC::recalcbanks ()
2277 {
2278         tick = false;
2279         bank_dirty = true;
2280 }
2281
2282 void
2283 OSC::_recalcbanks ()
2284 {
2285         if (observer_busy) {
2286                 return;
2287         }
2288         /*
2289          * We have two different ways of working here:
2290          * 1) banked: The controller has a bank of strips and only can deal
2291          * with banksize strips. We start banksize observers which run until
2292          * either banksize is changed or Ardour exits.
2293          *
2294          * 2) banksize is 0 or unlimited and so is the same size as the number
2295          * of strips. For a recalc, We want to tear down all strips but not send
2296          * a reset value for any of the controls and then rebuild all observers.
2297          * this is easier than detecting change in "bank" size and deleting or
2298          * adding just a few.
2299          */
2300
2301         // refresh each surface we know about.
2302         for (uint32_t it = 0; it < _surface.size(); ++it) {
2303                 OSCSurface* sur = &_surface[it];
2304                 // find lo_address
2305                 lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
2306                 if (sur->cue) {
2307                         _cue_set (sur->aux, addr);
2308                 } else if (!sur->bank_size) {
2309                         strip_feedback (sur, true);
2310                         // This surface uses /strip/list tell it routes have changed
2311                         lo_message reply;
2312                         reply = lo_message_new ();
2313                         lo_send_message (addr, X_("/strip/list"), reply);
2314                         lo_message_free (reply);
2315                 } else {
2316                         strip_feedback (sur, false);
2317                 }
2318                 _strip_select (boost::shared_ptr<ARDOUR::Stripable>(), addr);
2319         }
2320 }
2321
2322 int
2323 OSC::set_bank (uint32_t bank_start, lo_message msg)
2324 {
2325         return _set_bank (bank_start, get_address (msg));
2326 }
2327
2328 // set bank is callable with either message or address
2329 int
2330 OSC::_set_bank (uint32_t bank_start, lo_address addr)
2331 {
2332         if (!session) {
2333                 return -1;
2334         }
2335         if (!session->nroutes()) {
2336                 return -1;
2337         }
2338
2339         OSCSurface *s = get_surface (addr, true);
2340
2341         Sorted striplist = s->strips;
2342         uint32_t nstrips = s->nstrips;
2343
2344         LinkSet *set;
2345         uint32_t ls = s->linkset;
2346
2347         if (ls) {
2348                 //we have a linkset... deal with each surface
2349                 set = &(link_sets[ls]);
2350                 if (set->not_ready) {
2351                         return 1;
2352                 }
2353                 uint32_t d_count = set->urls.size();
2354                 set->strips = striplist;
2355                 bank_start = bank_limits_check (bank_start, set->banksize, nstrips);
2356                 set->bank = bank_start;
2357                 uint32_t not_ready = 0;
2358                 for (uint32_t dv = 1; dv < d_count; dv++) {
2359                         if (set->urls[dv] != "") {
2360                                 string url = set->urls[dv];
2361                                 OSCSurface *sur = get_surface (lo_address_new_from_url (url.c_str()));
2362                                 if (sur->linkset != ls) {
2363                                         set->urls[dv] = "";
2364                                         not_ready = dv;
2365                                 } else {
2366                                         lo_address sur_addr = lo_address_new_from_url (sur->remote_url.c_str());
2367
2368                                         sur->bank = bank_start;
2369                                         bank_start = bank_start + sur->bank_size;
2370                                         strip_feedback (sur, false);
2371                                         _strip_select (boost::shared_ptr<ARDOUR::Stripable>(), sur_addr);
2372                                         bank_leds (sur);
2373                                         lo_address_free (sur_addr);
2374                                 }
2375                         } else {
2376                                 not_ready = dv;
2377                         }
2378                         if (not_ready) {
2379                                 if (!set->not_ready) {
2380                                         set->not_ready = not_ready;
2381                                 }
2382                                 set->bank = 1;
2383                                 break;
2384                         }
2385                 }
2386                 if (not_ready) {
2387                         surface_link_state (set);
2388                 }
2389
2390         } else {
2391
2392                 s->bank = bank_limits_check (bank_start, s->bank_size, nstrips);
2393                 strip_feedback (s, true);
2394                 _strip_select (boost::shared_ptr<ARDOUR::Stripable>(), addr);
2395                 bank_leds (s);
2396         }
2397
2398
2399         bank_dirty = false;
2400         tick = true;
2401         return 0;
2402 }
2403
2404 uint32_t
2405 OSC::bank_limits_check (uint32_t bank, uint32_t size, uint32_t total)
2406 {
2407         uint32_t b_size;
2408         if (!size) {
2409                 // no banking - bank includes all stripables
2410                 b_size = total;
2411         } else {
2412                 b_size = size;
2413         }
2414         // Do limits checking
2415         if (bank < 1) bank = 1;
2416         if (b_size >= total)  {
2417                 bank = 1;
2418         } else if (bank > ((total - b_size) + 1)) {
2419                 // top bank is always filled if there are enough strips for at least one bank
2420                 bank = (uint32_t)((total - b_size) + 1);
2421         }
2422         return bank;
2423 }
2424
2425 void
2426 OSC::bank_leds (OSCSurface* s)
2427 {
2428         uint32_t bank = 0;
2429         uint32_t size = 0;
2430         uint32_t total = 0;
2431         // light bankup or bankdown buttons if it is possible to bank in that direction
2432         lo_address addr = lo_address_new_from_url (s->remote_url.c_str());
2433         if (s->linkset) {
2434                 LinkSet *set;
2435                 set = &(link_sets[s->linkset]);
2436                 bank = set->bank;
2437                 size = set->banksize;
2438                 total = s->nstrips;
2439                 if (set->not_ready) {
2440                         total = 1;
2441                 }
2442         } else {
2443                 bank = s->bank;
2444                 size = s->bank_size;
2445                 total = s->nstrips;
2446         }
2447         if (size && (s->feedback[0] || s->feedback[1] || s->feedback[4])) {
2448                 lo_message reply;
2449                 reply = lo_message_new ();
2450                 if ((total <= size) || (bank > (total - size))) {
2451                         lo_message_add_int32 (reply, 0);
2452                 } else {
2453                         lo_message_add_int32 (reply, 1);
2454                 }
2455                 lo_send_message (addr, X_("/bank_up"), reply);
2456                 lo_message_free (reply);
2457                 reply = lo_message_new ();
2458                 if (bank > 1) {
2459                         lo_message_add_int32 (reply, 1);
2460                 } else {
2461                         lo_message_add_int32 (reply, 0);
2462                 }
2463                 lo_send_message (addr, X_("/bank_down"), reply);
2464                 lo_message_free (reply);
2465         }
2466 }
2467
2468 int
2469 OSC::bank_up (lo_message msg)
2470 {
2471         return bank_delta (1.0, msg);
2472 }
2473
2474 int
2475 OSC::bank_delta (float delta, lo_message msg)
2476 {
2477         if (!session) {
2478                 return -1;
2479         }
2480         // only do deltas of -1 0 or 1
2481         if (delta > 0) {
2482                 delta = 1;
2483         } else if (delta < 0) {
2484                 delta = -1;
2485         } else {
2486                 // 0  key release ignore
2487                 return 0;
2488         }
2489         OSCSurface *s = get_surface(get_address (msg));
2490         if (!s->bank_size) {
2491                 // bank size of 0 means use all strips no banking
2492                 return 0;
2493         }
2494         uint32_t old_bank = 0;
2495         uint32_t bank_size = 0;
2496         if (s->linkset) {
2497                 old_bank = link_sets[s->linkset].bank;
2498                 bank_size = link_sets[s->linkset].banksize;
2499         } else {
2500                 old_bank = s->bank;
2501                 bank_size = s->bank_size;
2502         }
2503         uint32_t new_bank = old_bank + (bank_size * (int) delta);
2504         if ((int)new_bank < 1) {
2505                 new_bank = 1;
2506         }
2507         if (new_bank != old_bank) {
2508                 set_bank (new_bank, msg);
2509         }
2510         return 0;
2511 }
2512
2513 int
2514 OSC::bank_down (lo_message msg)
2515 {
2516         return bank_delta (-1.0, msg);
2517 }
2518
2519 int
2520 OSC::use_group (float value, lo_message msg)
2521 {
2522         if (!session) {
2523                 return -1;
2524         }
2525         OSCSurface *s = get_surface(get_address (msg));
2526         if (value) {
2527                 s->usegroup = PBD::Controllable::UseGroup;
2528         } else {
2529                 s->usegroup = PBD::Controllable::NoGroup;
2530         }
2531         return 0;
2532 }
2533
2534 // this gets called for anything that starts with /select/group
2535 int
2536 OSC::parse_sel_group (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
2537 {
2538         OSCSurface *sur = get_surface(get_address (msg));
2539         boost::shared_ptr<Stripable> s;
2540         if (sur->expand_enable) {
2541                 s = get_strip (sur->expand, get_address (msg));
2542         } else {
2543                 s = _select;
2544         }
2545         int ret = 1; /* unhandled */
2546         if (s) {
2547                 if (!strncmp (path, X_("/select/group"), 13)) {
2548                         if (argc == 1) {
2549                                 if (types[0] == 's') {
2550                                         return strip_select_group (s, &argv[0]->s);
2551                                 }
2552                         }
2553                 }
2554                 boost::shared_ptr<Route> rt = boost::dynamic_pointer_cast<Route> (s);
2555                 if (!rt) {
2556                         PBD::warning << "OSC: VCAs can not be part of a group." << endmsg;
2557                         return ret;
2558                 }
2559                 RouteGroup *rg = rt->route_group();
2560                 if (!rg) {
2561                         PBD::warning << "OSC: This strip is not part of a group." << endmsg;
2562                         return ret;
2563                 }
2564                 float value = 0;
2565                 if (argc == 1) {
2566                         if (types[0] == 'f') {
2567                                 value = (uint32_t) argv[0]->f;
2568                         } else if (types[0] == 'i') {
2569                                 value = (uint32_t) argv[0]->i;
2570                         }
2571                 }
2572                 if (!strncmp (path, X_("/select/group/enable"), 20)) {
2573                         if (argc == 1) {
2574                                 rg->set_active (value, this);
2575                                 ret = 0;
2576                         }
2577                 }
2578                 else if (!strncmp (path, X_("/select/group/only"), 18)) {
2579                         if ((argc == 1 && value) || !argc) {
2580                                 // fill sur->strips with routes from this group and hit bank1
2581                                 sur->temp_strips.clear();
2582                                 boost::shared_ptr<RouteList> rl = rg->route_list();
2583                                 for (RouteList::iterator it = rl->begin(); it != rl->end(); ++it) {
2584                                         boost::shared_ptr<Route> r = *it;
2585                                         boost::shared_ptr<Stripable> s = boost::dynamic_pointer_cast<Stripable> (r);
2586                                         sur->temp_strips.push_back(s);
2587                                 }
2588                                 sur->custom_mode = 7;
2589                                 set_bank (1, msg);
2590                                 ret = 0;
2591                         } else {
2592                                 // key off is ignored
2593                                 ret = 0;
2594                         }
2595                 }
2596                 else if (!strncmp (path, X_("/select/group/sharing"), 21)) {
2597                         if (argc == 9) {
2598                                 if (rg->is_gain() != (bool) argv[0]->i) {
2599                                         rg->set_gain ((bool) argv[0]->i);
2600                                 }
2601                                 if (rg->is_relative() != (bool) argv[1]->i) {
2602                                         rg->set_relative ((bool) argv[1]->i, this);
2603                                 }
2604                                 if (rg->is_mute() != (bool) argv[2]->i) {
2605                                         rg->set_mute ((bool) argv[2]->i);
2606                                 }
2607                                 if (rg->is_solo() != (bool) argv[3]->i) {
2608                                         rg->set_solo ((bool) argv[3]->i);
2609                                 }
2610                                 if (rg->is_recenable() != (bool) argv[4]->i) {
2611                                         rg->set_recenable ((bool) argv[4]->i);
2612                                 }
2613                                 if (rg->is_select() != (bool) argv[5]->i) {
2614                                         rg->set_select ((bool) argv[5]->i);
2615                                 }
2616                                 if (rg->is_route_active() != (bool) argv[6]->i) {
2617                                         rg->set_route_active ((bool) argv[6]->i);
2618                                 }
2619                                 if (rg->is_color() != (bool) argv[7]->i) {
2620                                         rg->set_color ((bool) argv[7]->i);
2621                                 }
2622                                 if (rg->is_monitoring() != (bool) argv[8]->i) {
2623                                         rg->set_monitoring ((bool) argv[8]->i);
2624                                 }
2625                                 ret = 0;
2626                         } else {
2627                                 PBD::warning << "OSC: Sharing can only be set if all 9 parameters are sent." << endmsg;
2628                         }
2629                 }
2630         }
2631         return ret;
2632  }
2633
2634 // this gets called for anything that starts with /select/vca
2635 int
2636 OSC::parse_sel_vca (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
2637 {
2638         OSCSurface *sur = get_surface(get_address (msg));
2639         boost::shared_ptr<Stripable> s;
2640         if (sur->expand_enable) {
2641                 s = get_strip (sur->expand, get_address (msg));
2642         } else {
2643                 s = _select;
2644         }
2645         int ret = 1; /* unhandled */
2646         if (s) {
2647                 string svalue = "";
2648                 uint32_t ivalue = 1024;
2649                 if (strcmp (path, X_("/select/vca")) == 0) {
2650                         if (argc == 2) {
2651                                 if (types[0] == 's') {
2652                                         svalue = &argv[0]->s;
2653                                         if (types[1] == 'i') {
2654                                                 ivalue = argv[1]->i;
2655                                         } else if (types[1] == 'f') {
2656                                                 ivalue = (uint32_t) argv[1]->f;
2657                                         } else {
2658                                                 return 1;
2659                                         }
2660                                         boost::shared_ptr<VCA> vca = get_vca_by_name (svalue);
2661                                         if (vca) {
2662                                                 boost::shared_ptr<Slavable> slv = boost::dynamic_pointer_cast<Slavable> (s);
2663                                                 if (ivalue) {
2664                                                         slv->assign (vca);
2665                                                 } else {
2666                                                         slv->unassign (vca);
2667                                                 }
2668                                                 ret = 0;
2669                                         }
2670                                 }
2671                         } else {
2672                                 PBD::warning << "OSC: setting a vca needs both the vca name and it's state" << endmsg;
2673                         }
2674                 }
2675                 else if (!strncmp (path, X_("/select/vca/only"), 16)) {
2676                         if (argc == 1) {
2677                                 if (types[0] == 'f') {
2678                                         ivalue = (uint32_t) argv[0]->f;
2679                                 } else if (types[0] == 'i') {
2680                                         ivalue = (uint32_t) argv[0]->i;
2681                                 }
2682                         }
2683                         boost::shared_ptr<VCA> vca = boost::dynamic_pointer_cast<VCA> (s);
2684                         if (vca) {
2685                                 if ((argc == 1 && ivalue) || !argc) {
2686                                         sur->temp_strips.clear();
2687                                         StripableList stripables;
2688                                         session->get_stripables (stripables);
2689                                         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
2690                                                 boost::shared_ptr<Stripable> st = *it;
2691                                                 if (st->slaved_to (vca)) {
2692                                                         sur->temp_strips.push_back(st);
2693                                                 }
2694                                         }
2695                                         sur->temp_strips.push_back(s);
2696                                         sur->custom_mode = 7;
2697                                         set_bank (1, msg);
2698                                         ret = 0;
2699                                 } else {
2700                                         // key off is ignored
2701                                         ret = 0;
2702                                 }
2703                         } else {
2704                                 PBD::warning << "OSC: Select is not a VCA right now" << endmsg;
2705                         }
2706                 }
2707         }
2708         return ret;
2709 }
2710
2711 boost::shared_ptr<VCA>
2712 OSC::get_vca_by_name (std::string vname)
2713 {
2714         StripableList stripables;
2715         session->get_stripables (stripables);
2716         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
2717                 boost::shared_ptr<Stripable> s = *it;
2718                 boost::shared_ptr<VCA> v = boost::dynamic_pointer_cast<VCA> (s);
2719                 if (v) {
2720                         if (vname == v->name()) {
2721                                 return v;
2722                         }
2723                 }
2724         }
2725         return boost::shared_ptr<VCA>();
2726 }
2727
2728 int
2729 OSC::name_session (char *n, lo_message msg)
2730 {
2731         if (!session) {
2732                 return -1;
2733         }
2734         string new_name = n;
2735         char illegal = Session::session_name_is_legal (new_name);
2736
2737         if (illegal) {
2738                 PBD::warning  << (string_compose (_("To ensure compatibility with various systems\n"
2739                                     "session names may not contain a '%1' character"), illegal)) << endmsg;
2740                 return -1;
2741         }
2742         switch (session->rename (new_name)) {
2743                 case -1:
2744                         PBD::warning  << (_("That name is already in use by another directory/folder. Please try again.")) << endmsg;
2745                         break;
2746                 case 0:
2747                         return 0;
2748                         break;
2749                 default:
2750                         PBD::warning  << (_("Renaming this session failed.\nThings could be seriously messed up at this point")) << endmsg;
2751                         break;
2752         }
2753         return -1;
2754 }
2755
2756 uint32_t
2757 OSC::get_sid (boost::shared_ptr<ARDOUR::Stripable> strip, lo_address addr)
2758 {
2759         if (!strip) {
2760                 return 0;
2761         }
2762
2763         OSCSurface *s = get_surface(addr);
2764
2765         uint32_t b_size;
2766         if (!s->bank_size) {
2767                 // no banking
2768                 b_size = s->nstrips;
2769         } else {
2770                 b_size = s->bank_size;
2771         }
2772
2773         for (uint32_t n = s->bank; n < (min ((b_size + s->bank), s->nstrips + 1)); ++n) {
2774                 if (n <= s->strips.size()) {
2775                         if (strip == s->strips[n-1]) {
2776                                 return n - s->bank + 1;
2777                         }
2778                 }
2779         }
2780         // failsafe... should never get here.
2781         return 0;
2782 }
2783
2784 boost::shared_ptr<ARDOUR::Stripable>
2785 OSC::get_strip (uint32_t ssid, lo_address addr)
2786 {
2787         OSCSurface *s = get_surface(addr);
2788         if (ssid && ((ssid + s->bank - 2) < s->nstrips)) {
2789                 return s->strips[ssid + s->bank - 2];
2790         }
2791         // guess it is out of range
2792         return boost::shared_ptr<ARDOUR::Stripable>();
2793 }
2794
2795 // send and plugin paging commands
2796 int
2797 OSC::sel_send_pagesize (uint32_t size, lo_message msg)
2798 {
2799         OSCSurface *s = get_surface(get_address (msg));
2800         if  (size != s->send_page_size) {
2801                 s->send_page_size = size;
2802                 s->sel_obs->set_send_size(size);
2803         }
2804         return 0;
2805 }
2806
2807 int
2808 OSC::sel_send_page (int page, lo_message msg)
2809 {
2810         OSCSurface *s = get_surface(get_address (msg));
2811         uint32_t send_size = s->send_page_size;
2812         if (!send_size) {
2813                 send_size = s->nsends;
2814         }
2815         uint32_t max_page = (uint32_t)(s->nsends / send_size) + 1;
2816         s->send_page = s->send_page + page;
2817         if (s->send_page < 1) {
2818                 s->send_page = 1;
2819         } else if ((uint32_t)s->send_page > max_page) {
2820                 s->send_page = max_page;
2821         }
2822         s->sel_obs->set_send_page (s->send_page);
2823         return 0;
2824 }
2825
2826 int
2827 OSC::sel_plug_pagesize (uint32_t size, lo_message msg)
2828 {
2829         OSCSurface *s = get_surface(get_address (msg));
2830         if (size != s->plug_page_size) {
2831                 s->plug_page_size = size;
2832                 s->sel_obs->set_plugin_size(size);
2833         }
2834         return 0;
2835 }
2836
2837 int
2838 OSC::sel_plug_page (int page, lo_message msg)
2839 {
2840         if (!page) {
2841                 return 0;
2842         }
2843         int new_page = 0;
2844         OSCSurface *s = get_surface(get_address (msg));
2845         if (page > 0) {
2846                 new_page = s->plug_page + s->plug_page_size;
2847                 if ((uint32_t) new_page > s->plug_params.size ()) {
2848                         new_page = s->plug_page;
2849                 }
2850         } else {
2851                 new_page = s->plug_page - s->plug_page_size;
2852                 if (new_page < 1) {
2853                         new_page = 1;
2854                 }
2855         }
2856         if (new_page != s->plug_page) {
2857                 s->plug_page = new_page;
2858                 s->sel_obs->set_plugin_page(s->plug_page);
2859         }
2860         return 0;
2861 }
2862
2863 int
2864 OSC::sel_plugin (int delta, lo_message msg)
2865 {
2866         if (!delta) {
2867                 return 0;
2868         }
2869         OSCSurface *sur = get_surface(get_address (msg));
2870         return _sel_plugin (sur->plugin_id + delta, get_address (msg));
2871 }
2872
2873 int
2874 OSC::_sel_plugin (int id, lo_address addr)
2875 {
2876         OSCSurface *sur = get_surface(addr);
2877         boost::shared_ptr<Stripable> s = sur->select;
2878         if (s) {
2879                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
2880                 if (!r) {
2881                         return 1;
2882                 }
2883
2884                 // find out how many plugins we have
2885                 bool plugs;
2886                 int nplugs  = 0;
2887                 sur->plugins.clear();
2888                 do {
2889                         plugs = false;
2890                         if (r->nth_plugin (nplugs)) {
2891                                 if (r->nth_plugin(nplugs)->display_to_user()) {
2892 #ifdef MIXBUS
2893                                         // need to check for mixbus channel strips (and exclude them)
2894                                         boost::shared_ptr<Processor> proc = r->nth_plugin (nplugs);
2895                                         boost::shared_ptr<PluginInsert> pi;
2896                                         if ((pi = boost::dynamic_pointer_cast<PluginInsert>(proc))) {
2897
2898                                                 if (!pi->is_channelstrip()) {
2899 #endif
2900                                                         sur->plugins.push_back (nplugs);
2901                                                         nplugs++;
2902 #ifdef MIXBUS
2903                                                 }
2904                                         }
2905 #endif
2906                                 }
2907                                 plugs = true;
2908                         }
2909                 } while (plugs);
2910
2911                 // limit plugin_id to actual plugins
2912                 if (sur->plugins.size() < 1) {
2913                         sur->plugin_id = 0;
2914                         sur->plug_page = 1;
2915                         if (sur->sel_obs) {
2916                                 sur->sel_obs->set_plugin_id(-1, 1);
2917                         }
2918                         return 0;
2919                 } else if (id < 1) {
2920                         sur->plugin_id = 1;
2921                 } else if (sur->plugins.size() < (uint32_t) id) {
2922                         sur->plugin_id = sur->plugins.size();
2923                 } else {
2924                         sur->plugin_id = id;
2925                 }
2926
2927                 // we have a plugin number now get the processor
2928                 boost::shared_ptr<Processor> proc = r->nth_plugin (sur->plugins[sur->plugin_id - 1]);
2929                 boost::shared_ptr<PluginInsert> pi;
2930                 if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(proc))) {
2931                         PBD::warning << "OSC: Plugin: " << sur->plugin_id << " does not seem to be a plugin" << endmsg;                 
2932                         return 1;
2933                 }
2934                 boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
2935                 bool ok = false;
2936                 // put only input controls into a vector
2937                 sur->plug_params.clear ();
2938                 uint32_t nplug_params  = pip->parameter_count();
2939                 for ( uint32_t ppi = 0;  ppi < nplug_params; ++ppi) {
2940                         uint32_t controlid = pip->nth_parameter(ppi, ok);
2941                         if (!ok) {
2942                                 continue;
2943                         }
2944                         if (pip->parameter_is_input(controlid)) {
2945                                 sur->plug_params.push_back (ppi);
2946                         }
2947                 }
2948
2949                 sur->plug_page = 1;
2950
2951                 if (sur->sel_obs) {
2952                         sur->sel_obs->set_plugin_id(sur->plugins[sur->plugin_id - 1], sur->plug_page);
2953                 }
2954                 return 0;
2955         }
2956         return 1;
2957 }
2958
2959 void
2960 OSC::transport_sample (lo_message msg)
2961 {
2962         if (!session) {
2963                 return;
2964         }
2965         check_surface (msg);
2966         samplepos_t pos = session->transport_sample ();
2967
2968         lo_message reply = lo_message_new ();
2969         lo_message_add_int64 (reply, pos);
2970
2971         lo_send_message (get_address (msg), X_("/transport_frame"), reply);
2972
2973         lo_message_free (reply);
2974 }
2975
2976 void
2977 OSC::transport_speed (lo_message msg)
2978 {
2979         if (!session) {
2980                 return;
2981         }
2982         check_surface (msg);
2983         double ts = session->transport_speed ();
2984
2985         lo_message reply = lo_message_new ();
2986         lo_message_add_double (reply, ts);
2987
2988         lo_send_message (get_address (msg), X_("/transport_speed"), reply);
2989
2990         lo_message_free (reply);
2991 }
2992
2993 void
2994 OSC::record_enabled (lo_message msg)
2995 {
2996         if (!session) {
2997                 return;
2998         }
2999         check_surface (msg);
3000         int re = (int)session->get_record_enabled ();
3001
3002         lo_message reply = lo_message_new ();
3003         lo_message_add_int32 (reply, re);
3004
3005         lo_send_message (get_address (msg), X_("/record_enabled"), reply);
3006
3007         lo_message_free (reply);
3008 }
3009
3010 int
3011 OSC::scrub (float delta, lo_message msg)
3012 {
3013         if (!session) return -1;
3014         check_surface (msg);
3015
3016         scrub_place = session->transport_sample ();
3017
3018         float speed;
3019
3020         int64_t now = ARDOUR::get_microseconds ();
3021         int64_t diff = now - scrub_time;
3022         if (diff > 35000) {
3023                 // speed 1 (or 0 if jog wheel supports touch)
3024                 speed = delta;
3025         } else if ((diff > 20000) && (fabs(scrub_speed) == 1)) {
3026                 // add some hysteresis to stop excess speed jumps
3027                 speed = delta;
3028         } else {
3029                 speed = (int)(delta * 2);
3030         }
3031         scrub_time = now;
3032         if (scrub_speed == speed) {
3033                 // Already at that speed no change
3034                 return 0;
3035         }
3036         scrub_speed = speed;
3037
3038         if (speed > 0) {
3039                 if (speed == 1) {
3040                         session->request_transport_speed (.5);
3041                 } else {
3042                         session->request_transport_speed (9.9);
3043                 }
3044         } else if (speed < 0) {
3045                 if (speed == -1) {
3046                         session->request_transport_speed (-.5);
3047                 } else {
3048                         session->request_transport_speed (-1);
3049                 }
3050         } else {
3051                 session->request_transport_speed (0);
3052         }
3053
3054         return 0;
3055 }
3056
3057 int
3058 OSC::jog (float delta, lo_message msg)
3059 {
3060         if (!session) return -1;
3061
3062         OSCSurface *s = get_surface(get_address (msg));
3063
3064         switch(s->jogmode)
3065         {
3066                 case 0:
3067                         if (delta) {
3068                                 jump_by_seconds (delta / 5);
3069                         }
3070                         break;
3071                 case 1:
3072                         if (delta > 0) {
3073                                 access_action ("Common/nudge-playhead-forward");
3074                         } else if (delta < 0) {
3075                                 access_action ("Common/nudge-playhead-backward");
3076                         }
3077                         break;
3078                 case 2:
3079                         scrub (delta, msg);
3080                         break;
3081                 case 3:
3082                         if (delta) {
3083                                 double speed = get_transport_speed ();
3084                                 set_transport_speed (speed + (delta / 8.1));
3085                         } else {
3086                                 set_transport_speed (0);
3087                         }
3088                         break;
3089                 case 4:
3090                         if (delta > 0) {
3091                                 next_marker ();
3092                         } else if (delta < 0) {
3093                                 prev_marker ();
3094                         }
3095                         break;
3096                 case 5:
3097                         if (delta > 0) {
3098                                 access_action ("Editor/scroll-forward");
3099                         } else if (delta < 0) {
3100                                 access_action ("Editor/scroll-backward");
3101                         }
3102                         break;
3103                 case 6:
3104                         if (delta > 0) {
3105                                 set_bank (s->bank + 1, msg);
3106                         } else if (delta < 0) {
3107                                 set_bank (s->bank - 1, msg);
3108                         }
3109                         break;
3110                 case 7:
3111                         if (delta > 0) {
3112                                 bank_up (msg);
3113                         } else if (delta < 0) {
3114                                 bank_down (msg);
3115                         }
3116                         break;
3117                 default:
3118                         break;
3119
3120         }
3121         return 0;
3122
3123 }
3124
3125 int
3126 OSC::jog_mode (float mode, lo_message msg)
3127 {
3128         if (!session) return -1;
3129
3130         OSCSurface *s = get_surface(get_address (msg));
3131         if (get_transport_speed () != 1.0) {
3132                 set_transport_speed (0);
3133         }
3134         s->jogmode = (uint32_t) mode;
3135         s->global_obs->jog_mode (mode);
3136         return 0;
3137 }
3138
3139 // two structs to help with going to markers
3140 struct LocationMarker {
3141         LocationMarker (const std::string& l, samplepos_t w)
3142                 : label (l), when (w) {}
3143         std::string label;
3144         samplepos_t  when;
3145 };
3146
3147 struct LocationMarkerSort {
3148         bool operator() (const LocationMarker& a, const LocationMarker& b) {
3149                 return (a.when < b.when);
3150         }
3151 };
3152
3153 int
3154 OSC::set_marker (const char* types, lo_arg **argv, int argc, lo_message msg)
3155 {
3156         if (argc != 1) {
3157                 PBD::warning << "Wrong number of parameters, one only." << endmsg;
3158                 return -1;
3159         }
3160         const Locations::LocationList& ll (session->locations ()->list ());
3161         uint32_t marker = 0;
3162
3163         switch (types[0]) {
3164                 case 's':
3165                         {
3166                                 Location *cur_mark = 0;
3167                                 for (Locations::LocationList::const_iterator l = ll.begin(); l != ll.end(); ++l) {
3168                                         if ((*l)->is_mark ()) {
3169                                                 if (strcmp (&argv[0]->s, (*l)->name().c_str()) == 0) {
3170                                                         session->request_locate ((*l)->start (), false);
3171                                                         return 0;
3172                                                 } else if ((*l)->start () == session->transport_sample()) {
3173                                                         cur_mark = (*l);
3174                                                 }
3175                                         }
3176                                 }
3177                                 if (cur_mark) {
3178                                         cur_mark->set_name (&argv[0]->s);
3179                                         return 0;
3180                                 }
3181                                 PBD::warning << string_compose ("Marker: \"%1\" - does not exist", &argv[0]->s) << endmsg;
3182                                 return -1;
3183                         }
3184                         break;
3185                 case 'i':
3186                         marker = (uint32_t) argv[0]->i - 1;
3187                         break;
3188                 case 'f':
3189                         marker = (uint32_t) argv[0]->f - 1;
3190                         break;
3191                 default:
3192                         return -1;
3193                         break;
3194         }
3195         std::vector<LocationMarker> lm;
3196         // get Locations that are marks
3197         for (Locations::LocationList::const_iterator l = ll.begin(); l != ll.end(); ++l) {
3198                 if ((*l)->is_mark ()) {
3199                         lm.push_back (LocationMarker((*l)->name(), (*l)->start ()));
3200                 }
3201         }
3202         // sort them by position
3203         LocationMarkerSort location_marker_sort;
3204         std::sort (lm.begin(), lm.end(), location_marker_sort);
3205         // go there
3206         if (marker < lm.size()) {
3207                 session->request_locate (lm[marker].when, false);
3208                 return 0;
3209         }
3210         // we were unable to deal with things
3211         return -1;
3212 }
3213
3214 int
3215 OSC::group_list (lo_message msg)
3216 {
3217         return send_group_list (get_address (msg));
3218 }
3219
3220 int
3221 OSC::send_group_list (lo_address addr)
3222 {
3223         lo_message reply;
3224         reply = lo_message_new ();
3225
3226         lo_message_add_string (reply, X_("none"));
3227
3228         std::list<RouteGroup*> groups = session->route_groups ();
3229         for (std::list<RouteGroup *>::iterator i = groups.begin(); i != groups.end(); ++i) {
3230                 RouteGroup *rg = *i;
3231                 lo_message_add_string (reply, rg->name().c_str());
3232         }
3233         lo_send_message (addr, X_("/group/list"), reply);
3234         lo_message_free (reply);
3235         return 0;
3236 }
3237
3238 int
3239 OSC::click_level (float position)
3240 {
3241         if (!session) return -1;
3242         if (session->click_gain()->gain_control()) {
3243                 session->click_gain()->gain_control()->set_value (session->click_gain()->gain_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
3244         }
3245         return 0;
3246 }
3247
3248 // master and monitor calls
3249 int
3250 OSC::master_set_gain (float dB)
3251 {
3252         if (!session) return -1;
3253         boost::shared_ptr<Stripable> s = session->master_out();
3254         if (s) {
3255                 if (dB < -192) {
3256                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
3257                 } else {
3258                         float abs = dB_to_coefficient (dB);
3259                         float top = s->gain_control()->upper();
3260                         if (abs > top) {
3261                                 abs = top;
3262                         }
3263                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3264                 }
3265         }
3266         return 0;
3267 }
3268
3269 int
3270 OSC::master_delta_gain (float delta)
3271 {
3272         if (!session) return -1;
3273         boost::shared_ptr<Stripable> s = session->master_out();
3274         if (s) {
3275                 float dB = accurate_coefficient_to_dB (s->gain_control()->get_value()) + delta;
3276                 if (dB < -192) {
3277                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
3278                 } else {
3279                         float abs = dB_to_coefficient (dB);
3280                         float top = s->gain_control()->upper();
3281                         if (abs > top) {
3282                                 abs = top;
3283                         }
3284                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3285                 }
3286         }
3287         return 0;
3288 }
3289
3290 int
3291 OSC::master_set_fader (float position)
3292 {
3293         if (!session) return -1;
3294         boost::shared_ptr<Stripable> s = session->master_out();
3295         if (s) {
3296                 s->gain_control()->set_value (s->gain_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
3297         }
3298         return 0;
3299 }
3300
3301 int
3302 OSC::master_set_trim (float dB)
3303 {
3304         if (!session) return -1;
3305         boost::shared_ptr<Stripable> s = session->master_out();
3306
3307         if (s) {
3308                 s->trim_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
3309         }
3310
3311         return 0;
3312 }
3313
3314 int
3315 OSC::master_set_pan_stereo_position (float position, lo_message msg)
3316 {
3317         if (!session) return -1;
3318         OSCSurface *sur = get_surface(get_address (msg));
3319
3320         float endposition = .5;
3321         boost::shared_ptr<Stripable> s = session->master_out();
3322
3323         if (s) {
3324                 if (s->pan_azimuth_control()) {
3325                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
3326                         endposition = s->pan_azimuth_control()->internal_to_interface (s->pan_azimuth_control()->get_value ());
3327                 }
3328         }
3329
3330         if (sur->feedback[4]) {
3331                 lo_message reply = lo_message_new ();
3332                 lo_message_add_float (reply, endposition);
3333
3334                 lo_send_message (get_address (msg), X_("/master/pan_stereo_position"), reply);
3335                 lo_message_free (reply);
3336         }
3337
3338         return 0;
3339 }
3340
3341 int
3342 OSC::master_set_mute (uint32_t state)
3343 {
3344         if (!session) return -1;
3345
3346         boost::shared_ptr<Stripable> s = session->master_out();
3347
3348         if (s) {
3349                 s->mute_control()->set_value (state, PBD::Controllable::NoGroup);
3350         }
3351
3352         return 0;
3353 }
3354
3355 int
3356 OSC::master_select (lo_message msg)
3357 {
3358         if (!session) {
3359                 return -1;
3360         }
3361         OSCSurface *sur = get_surface(get_address (msg));
3362         sur->expand_enable = false;
3363         boost::shared_ptr<Stripable> s = session->master_out();
3364         if (s) {
3365                 SetStripableSelection (s);
3366         }
3367
3368         return 0;
3369 }
3370
3371 int
3372 OSC::monitor_set_gain (float dB)
3373 {
3374         if (!session) return -1;
3375         boost::shared_ptr<Stripable> s = session->monitor_out();
3376
3377         if (s) {
3378                 if (dB < -192) {
3379                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
3380                 } else {
3381                         float abs = dB_to_coefficient (dB);
3382                         float top = s->gain_control()->upper();
3383                         if (abs > top) {
3384                                 abs = top;
3385                         }
3386                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3387                 }
3388         }
3389         return 0;
3390 }
3391
3392 int
3393 OSC::monitor_delta_gain (float delta)
3394 {
3395         if (!session) return -1;
3396         boost::shared_ptr<Stripable> s = session->monitor_out();
3397         if (s) {
3398                 float dB = accurate_coefficient_to_dB (s->gain_control()->get_value()) + delta;
3399                 if (dB < -192) {
3400                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
3401                 } else {
3402                         float abs = dB_to_coefficient (dB);
3403                         float top = s->gain_control()->upper();
3404                         if (abs > top) {
3405                                 abs = top;
3406                         }
3407                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3408                 }
3409         }
3410         return 0;
3411 }
3412
3413 int
3414 OSC::monitor_set_fader (float position)
3415 {
3416         if (!session) return -1;
3417         boost::shared_ptr<Stripable> s = session->monitor_out();
3418         if (s) {
3419                 s->gain_control()->set_value (s->gain_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
3420         }
3421         return 0;
3422 }
3423
3424 int
3425 OSC::monitor_set_mute (uint32_t state)
3426 {
3427         if (!session) return -1;
3428
3429         if (session->monitor_out()) {
3430                 boost::shared_ptr<MonitorProcessor> mon = session->monitor_out()->monitor_control();
3431                 mon->set_cut_all (state);
3432         }
3433         return 0;
3434 }
3435
3436 int
3437 OSC::monitor_set_dim (uint32_t state)
3438 {
3439         if (!session) return -1;
3440
3441         if (session->monitor_out()) {
3442                 boost::shared_ptr<MonitorProcessor> mon = session->monitor_out()->monitor_control();
3443                 mon->set_dim_all (state);
3444         }
3445         return 0;
3446 }
3447
3448 int
3449 OSC::monitor_set_mono (uint32_t state)
3450 {
3451         if (!session) return -1;
3452
3453         if (session->monitor_out()) {
3454                 boost::shared_ptr<MonitorProcessor> mon = session->monitor_out()->monitor_control();
3455                 mon->set_mono (state);
3456         }
3457         return 0;
3458 }
3459
3460 int
3461 OSC::route_get_sends(lo_message msg) {
3462         if (!session) {
3463                 return -1;
3464         }
3465
3466         lo_arg **argv = lo_message_get_argv(msg);
3467
3468         int rid = argv[0]->i;
3469
3470         boost::shared_ptr<Stripable> strip = get_strip(rid, get_address(msg));
3471         if (!strip) {
3472                 return -1;
3473         }
3474
3475         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (strip);
3476         if (!r) {
3477                 return -1;
3478         }
3479
3480         lo_message reply = lo_message_new();
3481         lo_message_add_int32(reply, rid);
3482
3483         int i = 0;
3484         for (;;) {
3485                 boost::shared_ptr<Processor> p = r->nth_send(i++);
3486
3487                 if (!p) {
3488                         break;
3489                 }
3490
3491                 boost::shared_ptr<InternalSend> isend = boost::dynamic_pointer_cast<InternalSend> (p);
3492                 if (isend) {
3493                         lo_message_add_int32(reply, get_sid(isend->target_route(), get_address(msg)));
3494                         lo_message_add_string(reply, isend->name().c_str());
3495                         lo_message_add_int32(reply, i);
3496                         boost::shared_ptr<Amp> a = isend->amp();
3497                         lo_message_add_float(reply, a->gain_control()->internal_to_interface (a->gain_control()->get_value()));
3498                         lo_message_add_int32(reply, p->active() ? 1 : 0);
3499                 }
3500         }
3501         // if used dedicated message path to identify this reply in async operation.
3502         // Naming it #reply wont help the client to identify the content.
3503         lo_send_message(get_address (msg), X_("/strip/sends"), reply);
3504
3505         lo_message_free(reply);
3506
3507         return 0;
3508 }
3509
3510 int
3511 OSC::route_get_receives(lo_message msg) {
3512         if (!session) {
3513                 return -1;
3514         }
3515
3516         lo_arg **argv = lo_message_get_argv(msg);
3517
3518         uint32_t rid = argv[0]->i;
3519
3520
3521         boost::shared_ptr<Stripable> strip = get_strip(rid, get_address(msg));
3522         if (!strip) {
3523                 return -1;
3524         }
3525
3526         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (strip);
3527         if (!r) {
3528                 return -1;
3529         }
3530
3531         boost::shared_ptr<RouteList> route_list = session->get_routes();
3532
3533         lo_message reply = lo_message_new();
3534         lo_message_add_int32(reply, rid);
3535
3536         for (RouteList::iterator i = route_list->begin(); i != route_list->end(); ++i) {
3537                 boost::shared_ptr<Route> tr = boost::dynamic_pointer_cast<Route> (*i);
3538                 if (!tr) {
3539                         continue;
3540                 }
3541                 int j = 0;
3542
3543                 for (;;) {
3544                         boost::shared_ptr<Processor> p = tr->nth_send(j++);
3545
3546                         if (!p) {
3547                                 break;
3548                         }
3549
3550                         boost::shared_ptr<InternalSend> isend = boost::dynamic_pointer_cast<InternalSend> (p);
3551                         if (isend) {
3552                                 if( isend->target_route()->id() == r->id()){
3553                                         boost::shared_ptr<Amp> a = isend->amp();
3554
3555                                         lo_message_add_int32(reply, get_sid(tr, get_address(msg)));
3556                                         lo_message_add_string(reply, tr->name().c_str());
3557                                         lo_message_add_int32(reply, j);
3558                                         lo_message_add_float(reply, a->gain_control()->internal_to_interface (a->gain_control()->get_value()));
3559                                         lo_message_add_int32(reply, p->active() ? 1 : 0);
3560                                 }
3561                         }
3562                 }
3563         }
3564
3565         // I have used a dedicated message path to identify this reply in async operation.
3566         // Naming it #reply wont help the client to identify the content.
3567         lo_send_message(get_address (msg), X_("/strip/receives"), reply);
3568         lo_message_free(reply);
3569         return 0;
3570 }
3571
3572 // strip calls
3573
3574 int
3575 OSC::set_automation (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
3576 {
3577         if (!session) return -1;
3578
3579         int ret = 1;
3580         OSCSurface *sur = get_surface(get_address (msg));
3581         boost::shared_ptr<Stripable> strp = boost::shared_ptr<Stripable>();
3582         uint32_t ctr = 0;
3583         uint32_t aut = 0;
3584         uint32_t ssid;
3585
3586         if (argc) {
3587                 if (types[argc - 1] == 'f') {
3588                         aut = (int)argv[argc - 1]->f;
3589                 } else {
3590                         aut = argv[argc - 1]->i;
3591                 }
3592         }
3593
3594         //parse path first to find stripable
3595         if (!strncmp (path, X_("/strip/"), 7)) {
3596                 // find ssid and stripable
3597                 if (argc > 1) {
3598                         if (types[1] == 'f') {
3599                                 ssid = (uint32_t)argv[0]->f;
3600                         } else {
3601                                 ssid = argv[0]->i;
3602                         }
3603                         strp = get_strip (ssid, get_address (msg));
3604                 } else {
3605                         ssid = atoi (&(strrchr (path, '/' ))[1]);
3606                         strp = get_strip (ssid, get_address (msg));
3607                 }
3608                 ctr = 7;
3609         } else if (!strncmp (path, X_("/select/"), 8)) {
3610                 if (sur->expand_enable && sur->expand) {
3611                         strp = get_strip (sur->expand, get_address (msg));
3612                 } else {
3613                         strp = _select;
3614                 }
3615                 ctr = 8;
3616         } else {
3617                 return ret;
3618         }
3619         if (strp) {
3620                 boost::shared_ptr<AutomationControl> control = boost::shared_ptr<AutomationControl>();
3621                 // other automatable controls can be added by repeating the next 6.5 lines
3622                 if ((!strncmp (&path[ctr], X_("fader"), 5)) || (!strncmp (&path[ctr], X_("gain"), 4))) {
3623                         if (strp->gain_control ()) {
3624                                 control = strp->gain_control ();
3625                         } else {
3626                                 PBD::warning << "No fader for this strip" << endmsg;
3627                         }
3628                 } else {
3629                         PBD::warning << "Automation not available for " << path << endmsg;
3630                 }
3631
3632                 if (control) {
3633
3634                         switch (aut) {
3635                                 case 0:
3636                                         control->set_automation_state (ARDOUR::Off);
3637                                         ret = 0;
3638                                         break;
3639                                 case 1:
3640                                         control->set_automation_state (ARDOUR::Play);
3641                                         ret = 0;
3642                                         break;
3643                                 case 2:
3644                                         control->set_automation_state (ARDOUR::Write);
3645                                         ret = 0;
3646                                         break;
3647                                 case 3:
3648                                         control->set_automation_state (ARDOUR::Touch);
3649                                         ret = 0;
3650                                         break;
3651                                 default:
3652                                         break;
3653                         }
3654                 }
3655         }
3656
3657         return ret;
3658 }
3659
3660 int
3661 OSC::touch_detect (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
3662 {
3663         if (!session) return -1;
3664
3665         int ret = 1;
3666         OSCSurface *sur = get_surface(get_address (msg));
3667         boost::shared_ptr<Stripable> strp = boost::shared_ptr<Stripable>();
3668         uint32_t ctr = 0;
3669         uint32_t touch = 0;
3670         uint32_t ssid;
3671
3672         if (argc) {
3673                 if (types[argc - 1] == 'f') {
3674                         touch = (int)argv[argc - 1]->f;
3675                 } else {
3676                         touch = argv[argc - 1]->i;
3677                 }
3678         }
3679
3680         //parse path first to find stripable
3681         if (!strncmp (path, X_("/strip/"), 7)) {
3682                 // find ssid and stripable
3683                 if (argc > 1) {
3684                         if (types[0] == 'f') {
3685                                 ssid = (uint32_t)argv[0]->f;
3686                         } else {
3687                                 ssid = argv[0]->i;
3688                         }
3689                         strp = get_strip (ssid, get_address (msg));
3690                 } else {
3691                         ssid = atoi (&(strrchr (path, '/' ))[1]);
3692                         strp = get_strip (ssid, get_address (msg));
3693                 }
3694                 ctr = 7;
3695         } else if (!strncmp (path, X_("/select/"), 8)) {
3696                 if (sur->expand_enable && sur->expand) {
3697                         strp = get_strip (sur->expand, get_address (msg));
3698                 } else {
3699                         strp = _select;
3700                 }
3701                 ctr = 8;
3702         } else {
3703                 return ret;
3704         }
3705         if (strp) {
3706                 boost::shared_ptr<AutomationControl> control = boost::shared_ptr<AutomationControl>();
3707                 // other automatable controls can be added by repeating the next 6.5 lines
3708                 if ((!strncmp (&path[ctr], X_("fader"), 5)) || (!strncmp (&path[ctr], X_("gain"), 4))) {
3709                         if (strp->gain_control ()) {
3710                                 control = strp->gain_control ();
3711                         } else {
3712                                 PBD::warning << "No fader for this strip" << endmsg;
3713                         }
3714                 } else {
3715                         PBD::warning << "Automation not available for " << path << endmsg;
3716                 }
3717
3718                 if (control) {
3719                         if (touch) {
3720                                 //start touch
3721                                 control->start_touch (control->session().transport_sample());
3722                                 ret = 0;
3723                         } else {
3724                                 // end touch
3725                                 control->stop_touch (control->session().transport_sample());
3726                                 ret = 0;
3727                         }
3728                         // just in case some crazy surface starts sending control values before touch
3729                         FakeTouchMap::iterator x = _touch_timeout.find(control);
3730                         if (x != _touch_timeout.end()) {
3731                                 _touch_timeout.erase (x);
3732                         }
3733                 }
3734         }
3735
3736         return ret;
3737 }
3738
3739 int
3740 OSC::fake_touch (boost::shared_ptr<ARDOUR::AutomationControl> ctrl)
3741 {
3742         if (ctrl) {
3743                 //start touch
3744                 if (ctrl->automation_state() == Touch && !ctrl->touching ()) {
3745                 ctrl->start_touch (ctrl->session().transport_sample());
3746                 _touch_timeout[ctrl] = 10;
3747                 }
3748         }
3749
3750         return 0;
3751 }
3752
3753 int
3754 OSC::route_mute (int ssid, int yn, lo_message msg)
3755 {
3756         if (!session) return -1;
3757         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3758         OSCSurface *sur = get_surface(get_address (msg));
3759
3760         if (s) {
3761                 if (s->mute_control()) {
3762                         s->mute_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
3763                         return 0;
3764                 }
3765         }
3766
3767         return float_message_with_id (X_("/strip/mute"), ssid, 0, sur->feedback[2], get_address (msg));
3768 }
3769
3770 int
3771 OSC::sel_mute (uint32_t yn, lo_message msg)
3772 {
3773         OSCSurface *sur = get_surface(get_address (msg));
3774         boost::shared_ptr<Stripable> s;
3775         if (sur->expand_enable) {
3776                 s = get_strip (sur->expand, get_address (msg));
3777         } else {
3778                 s = _select;
3779         }
3780         if (s) {
3781                 if (s->mute_control()) {
3782                         s->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3783                         return 0;
3784                 }
3785         }
3786         return float_message(X_("/select/mute"), 0, get_address (msg));
3787 }
3788
3789 int
3790 OSC::route_solo (int ssid, int yn, lo_message msg)
3791 {
3792         if (!session) return -1;
3793         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3794         OSCSurface *sur = get_surface(get_address (msg));
3795
3796         if (s) {
3797                 if (s->solo_control()) {
3798                         s->solo_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
3799                 }
3800         }
3801
3802         return float_message_with_id (X_("/strip/solo"), ssid, 0, sur->feedback[2], get_address (msg));
3803 }
3804
3805 int
3806 OSC::route_solo_iso (int ssid, int yn, lo_message msg)
3807 {
3808         if (!session) return -1;
3809         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3810         OSCSurface *sur = get_surface(get_address (msg));
3811
3812         if (s) {
3813                 if (s->solo_isolate_control()) {
3814                         s->solo_isolate_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
3815                         return 0;
3816                 }
3817         }
3818
3819         return float_message_with_id (X_("/strip/solo_iso"), ssid, 0, sur->feedback[2], get_address (msg));
3820 }
3821
3822 int
3823 OSC::route_solo_safe (int ssid, int yn, lo_message msg)
3824 {
3825         if (!session) return -1;
3826         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
3827         OSCSurface *sur = get_surface(get_address (msg));
3828
3829         if (s) {
3830                 if (s->solo_safe_control()) {
3831                         s->solo_safe_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
3832                         return 0;
3833                 }
3834         }
3835
3836         return float_message_with_id (X_("/strip/solo_safe"), ssid, 0, sur->feedback[2], get_address (msg));
3837 }
3838
3839 int
3840 OSC::sel_solo (uint32_t yn, lo_message msg)
3841 {
3842         OSCSurface *sur = get_surface(get_address (msg));
3843         boost::shared_ptr<Stripable> s;
3844         if (sur->expand_enable) {
3845                 s = get_strip (sur->expand, get_address (msg));
3846         } else {
3847                 s = _select;
3848         }
3849         if (s) {
3850                 if (s->solo_control()) {
3851                         session->set_control (s->solo_control(), yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3852                 }
3853         }
3854         return float_message(X_("/select/solo"), 0, get_address (msg));
3855 }
3856
3857 int
3858 OSC::sel_solo_iso (uint32_t yn, lo_message msg)
3859 {
3860         OSCSurface *sur = get_surface(get_address (msg));
3861         boost::shared_ptr<Stripable> s;
3862         if (sur->expand_enable) {
3863                 s = get_strip (sur->expand, get_address (msg));
3864         } else {
3865                 s = _select;
3866         }
3867         if (s) {
3868                 if (s->solo_isolate_control()) {
3869                         s->solo_isolate_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3870                         return 0;
3871                 }
3872         }
3873         return float_message(X_("/select/solo_iso"), 0, get_address (msg));
3874 }
3875
3876 int
3877 OSC::sel_solo_safe (uint32_t yn, lo_message msg)
3878 {
3879         OSCSurface *sur = get_surface(get_address (msg));
3880         boost::shared_ptr<Stripable> s;
3881         if (sur->expand_enable) {
3882                 s = get_strip (sur->expand, get_address (msg));
3883         } else {
3884                 s = _select;
3885         }
3886         if (s) {
3887                 if (s->solo_safe_control()) {
3888                         s->solo_safe_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3889                         return 0;
3890                 }
3891         }
3892         return float_message(X_("/select/solo_safe"), 0, get_address (msg));
3893 }
3894
3895 int
3896 OSC::sel_recenable (uint32_t yn, lo_message msg)
3897 {
3898         OSCSurface *sur = get_surface(get_address (msg));
3899         boost::shared_ptr<Stripable> s;
3900         if (sur->expand_enable) {
3901                 s = get_strip (sur->expand, get_address (msg));
3902         } else {
3903                 s = _select;
3904         }
3905         if (s) {
3906                 if (s->rec_enable_control()) {
3907                         s->rec_enable_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3908                         if (s->rec_enable_control()->get_value()) {
3909                                 return 0;
3910                         }
3911                 }
3912         }
3913         return float_message(X_("/select/recenable"), 0, get_address (msg));
3914 }
3915
3916 int
3917 OSC::route_recenable (int ssid, int yn, lo_message msg)
3918 {
3919         if (!session) return -1;
3920         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3921         OSCSurface *sur = get_surface(get_address (msg));
3922
3923         if (s) {
3924                 if (s->rec_enable_control()) {
3925                         s->rec_enable_control()->set_value (yn, sur->usegroup);
3926                         if (s->rec_enable_control()->get_value()) {
3927                                 return 0;
3928                         }
3929                 }
3930         }
3931         return float_message_with_id (X_("/strip/recenable"), ssid, 0, sur->feedback[2], get_address (msg));
3932 }
3933
3934 int
3935 OSC::route_rename (int ssid, char *newname, lo_message msg) {
3936         if (!session) {
3937                 return -1;
3938         }
3939
3940         boost::shared_ptr<Stripable> s = get_strip(ssid, get_address(msg));
3941
3942         if (s) {
3943                 s->set_name(std::string(newname));
3944         }
3945
3946         return 0;
3947 }
3948
3949 int
3950 OSC::sel_rename (char *newname, lo_message msg) {
3951         if (!session) {
3952                 return -1;
3953         }
3954
3955         OSCSurface *sur = get_surface(get_address (msg));
3956         boost::shared_ptr<Stripable> s;
3957         if (sur->expand_enable) {
3958                 s = get_strip (sur->expand, get_address (msg));
3959         } else {
3960                 s = _select;
3961         }
3962         if (s) {
3963                 s->set_name(std::string(newname));
3964         }
3965
3966         return 0;
3967 }
3968
3969 int
3970 OSC::sel_comment (char *newcomment, lo_message msg) {
3971         if (!session) {
3972                 return -1;
3973         }
3974
3975         OSCSurface *sur = get_surface(get_address (msg));
3976         boost::shared_ptr<Stripable> s;
3977         if (sur->expand_enable) {
3978                 s = get_strip (sur->expand, get_address (msg));
3979         } else {
3980                 s = _select;
3981         }
3982         if (s) {
3983                 boost::shared_ptr<Route> rt = boost::dynamic_pointer_cast<Route> (s);
3984                 if (!rt) {
3985                         PBD::warning << "OSC: can not set comment on VCAs." << endmsg;
3986                         return -1;
3987                 }
3988                 rt->set_comment (newcomment, this);
3989         }
3990
3991         return 0;
3992 }
3993
3994 int
3995 OSC::strip_group (int ssid, char *group, lo_message msg) {
3996         if (!session) {
3997                 return -1;
3998         }
3999         boost::shared_ptr<Stripable> s = get_strip(ssid, get_address(msg));
4000         return strip_select_group (s, group);
4001 }
4002
4003 int
4004 OSC::sel_group (char *group, lo_message msg) {
4005         if (!session) {
4006                 return -1;
4007         }
4008         OSCSurface *sur = get_surface(get_address (msg));
4009         boost::shared_ptr<Stripable> s;
4010         if (sur->expand_enable) {
4011                 s = get_strip (sur->expand, get_address (msg));
4012         } else {
4013                 s = _select;
4014         }
4015         return strip_select_group (s, group);
4016 }
4017
4018 int
4019 OSC::strip_select_group (boost::shared_ptr<Stripable> s, char *group)
4020 {
4021         string grp = group;
4022         if (grp == "" || grp == " ") {
4023                         grp = "none";
4024                 }
4025
4026         if (s) {
4027                 boost::shared_ptr<Route> rt = boost::dynamic_pointer_cast<Route> (s);
4028                 if (!rt) {
4029                         PBD::warning << "OSC: VCAs can not be part of a group." << endmsg;
4030                         return -1;
4031                 }
4032                 RouteGroup *rg = rt->route_group();
4033                 RouteGroup* new_rg = session->route_group_by_name (grp);
4034                 if (rg) {
4035                         string old_group = rg->name();
4036                         if (grp == "none") {
4037                                 if (rg->size () == 1) {
4038                                         session->remove_route_group (*rg);
4039                                 } else {
4040                                         rg->remove (rt);
4041                                 }
4042                         } else if (grp != old_group) {
4043                                 if (new_rg) {
4044                                         // group exists switch to it
4045                                         if (rg->size () == 1) {
4046                                                 session->remove_route_group (rg);
4047                                         } else {
4048                                                 rg->remove (rt);
4049                                         }
4050                                         new_rg->add (rt);
4051                                 } else {
4052                                         rg->set_name (grp);
4053                                 }
4054                         } else {
4055                                 return 0;
4056                         }
4057                 } else {
4058                         if (grp == "none") {
4059                                 return 0;
4060                         } else if (new_rg) {
4061                                 new_rg->add (rt);
4062                         } else {
4063                                 // create new group with this strip in it
4064                                 RouteGroup* new_rg = new RouteGroup (*session, grp);
4065                                 session->add_route_group (new_rg);
4066                                 new_rg->add (rt);
4067                         }
4068                 }
4069         }
4070         return 0;
4071 }
4072
4073 int
4074 OSC::sel_recsafe (uint32_t yn, lo_message msg)
4075 {
4076         OSCSurface *sur = get_surface(get_address (msg));
4077         boost::shared_ptr<Stripable> s;
4078         if (sur->expand_enable) {
4079                 s = get_strip (sur->expand, get_address (msg));
4080         } else {
4081                 s = _select;
4082         }
4083         if (s) {
4084                 if (s->rec_safe_control()) {
4085                         s->rec_safe_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
4086                         if (s->rec_safe_control()->get_value()) {
4087                                 return 0;
4088                         }
4089                 }
4090         }
4091         return float_message(X_("/select/record_safe"), 0, get_address (msg));
4092 }
4093
4094 int
4095 OSC::route_recsafe (int ssid, int yn, lo_message msg)
4096 {
4097         if (!session) return -1;
4098         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4099         OSCSurface *sur = get_surface(get_address (msg));
4100         if (s) {
4101                 if (s->rec_safe_control()) {
4102                         s->rec_safe_control()->set_value (yn, sur->usegroup);
4103                         if (s->rec_safe_control()->get_value()) {
4104                                 return 0;
4105                         }
4106                 }
4107         }
4108         return float_message_with_id (X_("/strip/record_safe"), ssid, 0, sur->feedback[2], get_address (msg));
4109 }
4110
4111 int
4112 OSC::route_monitor_input (int ssid, int yn, lo_message msg)
4113 {
4114         if (!session) return -1;
4115         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4116         OSCSurface *sur = get_surface(get_address (msg));
4117
4118         if (s) {
4119                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
4120                 if (track) {
4121                         if (track->monitoring_control()) {
4122                                 std::bitset<32> value = track->monitoring_control()->get_value ();
4123                                 value[0] = yn ? 1 : 0;
4124                                 track->monitoring_control()->set_value (value.to_ulong(), sur->usegroup);
4125                                 return 0;
4126                         }
4127                 }
4128         }
4129
4130         return float_message_with_id (X_("/strip/monitor_input"), ssid, 0, sur->feedback[2], get_address (msg));
4131 }
4132
4133 int
4134 OSC::sel_monitor_input (uint32_t yn, lo_message msg)
4135 {
4136         OSCSurface *sur = get_surface(get_address (msg));
4137         boost::shared_ptr<Stripable> s;
4138         if (sur->expand_enable) {
4139                 s = get_strip (sur->expand, get_address (msg));
4140         } else {
4141                 s = _select;
4142         }
4143         if (s) {
4144                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
4145                 if (track) {
4146                         if (track->monitoring_control()) {
4147                                 std::bitset<32> value = track->monitoring_control()->get_value ();
4148                                 value[0] = yn ? 1 : 0;
4149                                 track->monitoring_control()->set_value (value.to_ulong(), sur->usegroup);
4150                                 return 0;
4151                         }
4152                 }
4153         }
4154         return float_message(X_("/select/monitor_input"), 0, get_address (msg));
4155 }
4156
4157 int
4158 OSC::route_monitor_disk (int ssid, int yn, lo_message msg)
4159 {
4160         if (!session) return -1;
4161         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4162         OSCSurface *sur = get_surface(get_address (msg));
4163
4164         if (s) {
4165                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
4166                 if (track) {
4167                         if (track->monitoring_control()) {
4168                                 std::bitset<32> value = track->monitoring_control()->get_value ();
4169                                 value[1] = yn ? 1 : 0;
4170                                 track->monitoring_control()->set_value (value.to_ulong(), sur->usegroup);
4171                                 return 0;
4172                         }
4173                 }
4174         }
4175
4176         return float_message_with_id (X_("/strip/monitor_disk"), ssid, 0, sur->feedback[2], get_address (msg));
4177 }
4178
4179 int
4180 OSC::sel_monitor_disk (uint32_t yn, lo_message msg)
4181 {
4182         OSCSurface *sur = get_surface(get_address (msg));
4183         boost::shared_ptr<Stripable> s;
4184         if (sur->expand_enable) {
4185                 s = get_strip (sur->expand, get_address (msg));
4186         } else {
4187                 s = _select;
4188         }
4189         if (s) {
4190                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
4191                 if (track) {
4192                         if (track->monitoring_control()) {
4193                                 std::bitset<32> value = track->monitoring_control()->get_value ();
4194                                 value[1] = yn ? 1 : 0;
4195                                 track->monitoring_control()->set_value (value.to_ulong(), sur->usegroup);
4196                                 return 0;
4197                         }
4198                 }
4199         }
4200         return float_message(X_("/select/monitor_disk"), 0, get_address (msg));
4201 }
4202
4203
4204 int
4205 OSC::strip_phase (int ssid, int yn, lo_message msg)
4206 {
4207         if (!session) return -1;
4208         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4209         OSCSurface *sur = get_surface(get_address (msg));
4210
4211         if (s) {
4212                 if (s->phase_control()) {
4213                         s->phase_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
4214                         return 0;
4215                 }
4216         }
4217
4218         return float_message_with_id (X_("/strip/polarity"), ssid, 0, sur->feedback[2], get_address (msg));
4219 }
4220
4221 int
4222 OSC::sel_phase (uint32_t yn, lo_message msg)
4223 {
4224         OSCSurface *sur = get_surface(get_address (msg));
4225         boost::shared_ptr<Stripable> s;
4226         if (sur->expand_enable) {
4227                 s = get_strip (sur->expand, get_address (msg));
4228         } else {
4229                 s = _select;
4230         }
4231         if (s) {
4232                 if (s->phase_control()) {
4233                         s->phase_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
4234                         return 0;
4235                 }
4236         }
4237         return float_message(X_("/select/polarity"), 0, get_address (msg));
4238 }
4239
4240 int
4241 OSC::strip_expand (int ssid, int yn, lo_message msg)
4242 {
4243         OSCSurface *sur = get_surface(get_address (msg));
4244         sur->expand_enable = (bool) yn;
4245         sur->expand = ssid;
4246         boost::shared_ptr<Stripable> s;
4247         if (yn) {
4248                 s = get_strip (ssid, get_address (msg));
4249         } else {
4250                 s = _select;
4251         }
4252
4253         return _strip_select (s, get_address (msg));
4254 }
4255
4256 int
4257 OSC::strip_hide (int ssid, int state, lo_message msg)
4258 {
4259         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4260
4261         if (s) {
4262                 if (state != s->is_hidden ()) {
4263                         s->presentation_info().set_hidden ((bool) state);
4264                 }
4265         }
4266         return 0;
4267 }
4268
4269 int
4270 OSC::_strip_select (boost::shared_ptr<Stripable> s, lo_address addr)
4271 {
4272         if (!session) {
4273                 return -1;
4274         }
4275         OSCSurface *sur = get_surface(addr, true);
4276         if (!s) {
4277                 // expand doesn't point to a stripable, turn it off and use select
4278                 sur->expand = 0;
4279                 sur->expand_enable = false;
4280                 if (ControlProtocol::first_selected_stripable()) {
4281                         s = ControlProtocol::first_selected_stripable();
4282                 } else {
4283                         s = session->master_out ();
4284                 }
4285                         _select = s;
4286         }
4287         sur->select = s;
4288         bool sends;
4289         uint32_t nsends  = 0;
4290         do {
4291                 sends = false;
4292                 if (s->send_level_controllable (nsends)) {
4293                         sends = true;
4294                         nsends++;
4295                 }
4296         } while (sends);
4297         sur->nsends = nsends;
4298
4299         s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
4300
4301         OSCSelectObserver* so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs);
4302         if (sur->feedback[13]) {
4303                 if (so != 0) {
4304                         so->refresh_strip (s, nsends, sur->gainmode, true);
4305                 } else {
4306                         OSCSelectObserver* sel_fb = new OSCSelectObserver (*this, *session, sur);
4307                         sur->sel_obs = sel_fb;
4308                 }
4309                 sur->sel_obs->set_expand (sur->expand_enable);
4310                 uint32_t obs_expand = 0;
4311                 if (sur->expand_enable) {
4312                         obs_expand = sur->expand;
4313                 } else {
4314                         obs_expand = 0;
4315                 }
4316                 for (uint32_t i = 0; i < sur->observers.size(); i++) {
4317                         sur->observers[i]->set_expand (obs_expand);
4318                 }
4319         } else {
4320                 if (so != 0) {
4321                         delete so;
4322                         sur->sel_obs = 0;
4323                 }
4324         }
4325         // need to set monitor for processor changed signal (for paging)
4326         string address = lo_address_get_url (addr);
4327         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
4328         if (r) {
4329                 r->processors_changed.connect  (sur->proc_connection, MISSING_INVALIDATOR, boost::bind (&OSC::processor_changed, this, address), this);
4330                 _sel_plugin (sur->plugin_id, addr);
4331         }
4332
4333         return 0;
4334 }
4335
4336 void
4337 OSC::processor_changed (string address)
4338 {
4339         lo_address addr = lo_address_new_from_url (address.c_str());
4340         OSCSurface *sur = get_surface (addr);
4341         _sel_plugin (sur->plugin_id, addr);
4342         if (sur->sel_obs) {
4343                 sur->sel_obs->renew_sends ();
4344                 sur->sel_obs->eq_restart (-1);
4345         }
4346 }
4347
4348 int
4349 OSC::strip_gui_select (int ssid, int yn, lo_message msg)
4350 {
4351         //ignore button release
4352         if (!yn) return 0;
4353
4354         if (!session) {
4355                 return -1;
4356         }
4357         OSCSurface *sur = get_surface(get_address (msg));
4358         sur->expand_enable = false;
4359         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4360         if (s) {
4361                 SetStripableSelection (s);
4362         } else {
4363                 if ((int) (sur->feedback.to_ulong())) {
4364                         float_message_with_id (X_("/strip/select"), ssid, 0, sur->feedback[2], get_address (msg));
4365                 }
4366         }
4367
4368         return 0;
4369 }
4370
4371 int
4372 OSC::sel_expand (uint32_t state, lo_message msg)
4373 {
4374         OSCSurface *sur = get_surface(get_address (msg));
4375         boost::shared_ptr<Stripable> s;
4376         if (state && sur->expand) {
4377                 sur->expand_enable = (bool) state;
4378                 s = get_strip (sur->expand, get_address (msg));
4379         } else {
4380                 sur->expand_enable = false;
4381                 s = _select;
4382         }
4383
4384         return _strip_select (s, get_address (msg));
4385 }
4386
4387 int
4388 OSC::route_set_gain_dB (int ssid, float dB, lo_message msg)
4389 {
4390         if (!session) {
4391                 return -1;
4392         }
4393         OSCSurface *sur = get_surface(get_address (msg));
4394         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4395         if (s) {
4396                 float abs;
4397                 if (s->gain_control()) {
4398                         if (dB < -192) {
4399                                 abs = 0;
4400                         } else {
4401                                 abs = dB_to_coefficient (dB);
4402                                 float top = s->gain_control()->upper();
4403                                 if (abs > top) {
4404                                         abs = top;
4405                                 }
4406                         }
4407                         fake_touch (s->gain_control());
4408                         s->gain_control()->set_value (abs, sur->usegroup);
4409                         return 0;
4410                 }
4411         }
4412         return float_message_with_id (X_("/strip/gain"), ssid, -193, sur->feedback[2], get_address (msg));
4413 }
4414
4415 int
4416 OSC::sel_gain (float val, lo_message msg)
4417 {
4418         OSCSurface *sur = get_surface(get_address (msg));
4419         boost::shared_ptr<Stripable> s;
4420         if (sur->expand_enable) {
4421                 s = get_strip (sur->expand, get_address (msg));
4422         } else {
4423                 s = _select;
4424         }
4425         if (s) {
4426                 float abs;
4427                 if (s->gain_control()) {
4428                         if (val < -192) {
4429                                 abs = 0;
4430                         } else {
4431                                 abs = dB_to_coefficient (val);
4432                                 float top = s->gain_control()->upper();
4433                                 if (abs > top) {
4434                                         abs = top;
4435                                 }
4436                         }
4437                         fake_touch (s->gain_control());
4438                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
4439                         return 0;
4440                 }
4441         }
4442         return float_message(X_("/select/gain"), -193, get_address (msg));
4443 }
4444
4445 int
4446 OSC::sel_dB_delta (float delta, lo_message msg)
4447 {
4448         OSCSurface *sur = get_surface(get_address (msg));
4449         boost::shared_ptr<Stripable> s;
4450         if (sur->expand_enable) {
4451                 s = get_strip (sur->expand, get_address (msg));
4452         } else {
4453                 s = _select;
4454         }
4455         if (s) {
4456                 if (s->gain_control()) {
4457                         float dB = accurate_coefficient_to_dB (s->gain_control()->get_value()) + delta;
4458                         float abs;
4459                         if (dB < -192) {
4460                                 abs = 0;
4461                         } else {
4462                                 abs = dB_to_coefficient (dB);
4463                                 float top = s->gain_control()->upper();
4464                                 if (abs > top) {
4465                                         abs = top;
4466                                 }
4467                         }
4468                         fake_touch (s->gain_control());
4469                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
4470                         return 0;
4471                 }
4472         }
4473         return float_message(X_("/select/gain"), -193, get_address (msg));
4474 }
4475
4476 int
4477 OSC::route_set_gain_fader (int ssid, float pos, lo_message msg)
4478 {
4479         if (!session) {
4480                 return -1;
4481         }
4482         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4483         OSCSurface *sur = get_surface(get_address (msg));
4484
4485         if (s) {
4486                 if (s->gain_control()) {
4487                         fake_touch (s->gain_control());
4488                         s->gain_control()->set_value (s->gain_control()->interface_to_internal (pos), sur->usegroup);
4489                 } else {
4490                         return float_message_with_id (X_("/strip/fader"), ssid, 0, sur->feedback[2], get_address (msg));
4491                 }
4492         } else {
4493                 return float_message_with_id (X_("/strip/fader"), ssid, 0, sur->feedback[2], get_address (msg));
4494         }
4495         return 0;
4496 }
4497
4498 int
4499 OSC::strip_db_delta (int ssid, float delta, lo_message msg)
4500 {
4501         if (!session) return -1;
4502         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4503         OSCSurface *sur = get_surface(get_address (msg));
4504         if (s) {
4505                 float db = accurate_coefficient_to_dB (s->gain_control()->get_value()) + delta;
4506                 float abs;
4507                 if (db < -192) {
4508                         abs = 0;
4509                 } else {
4510                         abs = dB_to_coefficient (db);
4511                         float top = s->gain_control()->upper();
4512                         if (abs > top) {
4513                                 abs = top;
4514                         }
4515                 }
4516                 s->gain_control()->set_value (abs, sur->usegroup);
4517                 return 0;
4518         }
4519         return -1;
4520 }
4521
4522 int
4523 OSC::sel_fader (float val, lo_message msg)
4524 {
4525         OSCSurface *sur = get_surface(get_address (msg));
4526         boost::shared_ptr<Stripable> s;
4527         if (sur->expand_enable) {
4528                 s = get_strip (sur->expand, get_address (msg));
4529         } else {
4530                 s = _select;
4531         }
4532         if (s) {
4533                 if (s->gain_control()) {
4534                         fake_touch (s->gain_control());
4535                         s->gain_control()->set_value (s->gain_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
4536                         return 0;
4537                 }
4538         }
4539         return float_message(X_("/select/fader"), 0, get_address (msg));
4540 }
4541
4542 int
4543 OSC::route_set_trim_abs (int ssid, float level, lo_message msg)
4544 {
4545         if (!session) return -1;
4546         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4547         OSCSurface *sur = get_surface(get_address (msg));
4548
4549         if (s) {
4550                 if (s->trim_control()) {
4551                         s->trim_control()->set_value (level, sur->usegroup);
4552                         return 0;
4553                 }
4554
4555         }
4556
4557         return -1;
4558 }
4559
4560 int
4561 OSC::route_set_trim_dB (int ssid, float dB, lo_message msg)
4562 {
4563         OSCSurface *sur = get_surface(get_address (msg));
4564         int ret;
4565         ret = route_set_trim_abs(ssid, dB_to_coefficient (dB), msg);
4566         if (ret != 0) {
4567                 return float_message_with_id (X_("/strip/trimdB"), ssid, 0, sur->feedback[2], get_address (msg));
4568         }
4569
4570 return 0;
4571 }
4572
4573 int
4574 OSC::sel_trim (float val, lo_message msg)
4575 {
4576         OSCSurface *sur = get_surface(get_address (msg));
4577         boost::shared_ptr<Stripable> s;
4578         if (sur->expand_enable) {
4579                 s = get_strip (sur->expand, get_address (msg));
4580         } else {
4581                 s = _select;
4582         }
4583         if (s) {
4584                 if (s->trim_control()) {
4585                         s->trim_control()->set_value (dB_to_coefficient (val), PBD::Controllable::NoGroup);
4586                         return 0;
4587                 }
4588         }
4589         return float_message(X_("/select/trimdB"), 0, get_address (msg));
4590 }
4591
4592 int
4593 OSC::sel_hide (uint32_t state, lo_message msg)
4594 {
4595         OSCSurface *sur = get_surface(get_address (msg));
4596         boost::shared_ptr<Stripable> s;
4597         if (sur->expand_enable) {
4598                 s = get_strip (sur->expand, get_address (msg));
4599         } else {
4600                 s = _select;
4601         }
4602         if (s) {
4603                 if (state != s->is_hidden ()) {
4604                         s->presentation_info().set_hidden ((bool) state);
4605                 }
4606         }
4607         return 0;
4608 }
4609
4610 int
4611 OSC::sel_pan_position (float val, lo_message msg)
4612 {
4613         OSCSurface *sur = get_surface(get_address (msg));
4614         boost::shared_ptr<Stripable> s;
4615         if (sur->expand_enable) {
4616                 s = get_strip (sur->expand, get_address (msg));
4617         } else {
4618                 s = _select;
4619         }
4620         if (s) {
4621                 if(s->pan_azimuth_control()) {
4622                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
4623                         return 0;
4624                 }
4625         }
4626         return float_message(X_("/select/pan_stereo_position"), 0.5, get_address (msg));
4627 }
4628
4629 int
4630 OSC::sel_pan_width (float val, lo_message msg)
4631 {
4632         OSCSurface *sur = get_surface(get_address (msg));
4633         boost::shared_ptr<Stripable> s;
4634         if (sur->expand_enable) {
4635                 s = get_strip (sur->expand, get_address (msg));
4636         } else {
4637                 s = _select;
4638         }
4639         if (s) {
4640                 if (s->pan_width_control()) {
4641                         s->pan_width_control()->set_value (s->pan_width_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
4642                         return 0;
4643                 }
4644         }
4645         return float_message(X_("/select/pan_stereo_width"), 1, get_address (msg));
4646 }
4647
4648 int
4649 OSC::route_set_pan_stereo_position (int ssid, float pos, lo_message msg)
4650 {
4651         if (!session) return -1;
4652         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4653         OSCSurface *sur = get_surface(get_address (msg));
4654
4655         if (s) {
4656                 if(s->pan_azimuth_control()) {
4657                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (pos), sur->usegroup);
4658                         return 0;
4659                 }
4660         }
4661
4662         return float_message_with_id (X_("/strip/pan_stereo_position"), ssid, 0.5, sur->feedback[2], get_address (msg));
4663 }
4664
4665 int
4666 OSC::route_set_pan_stereo_width (int ssid, float pos, lo_message msg)
4667 {
4668         if (!session) return -1;
4669         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4670         OSCSurface *sur = get_surface(get_address (msg));
4671
4672         if (s) {
4673                 if (s->pan_width_control()) {
4674                         s->pan_width_control()->set_value (pos, sur->usegroup);
4675                         return 0;
4676                 }
4677         }
4678
4679         return float_message_with_id (X_("/strip/pan_stereo_width"), ssid, 1, sur->feedback[2], get_address (msg));
4680 }
4681
4682 int
4683 OSC::route_set_send_gain_dB (int ssid, int id, float val, lo_message msg)
4684 {
4685         if (!session) {
4686                 return -1;
4687         }
4688         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4689         OSCSurface *sur = get_surface(get_address (msg));
4690         float abs;
4691         if (s) {
4692                 if (id > 0) {
4693                         --id;
4694                 }
4695 #ifdef MIXBUS
4696                 abs = val;
4697 #else
4698                 if (val < -192) {
4699                         abs = 0;
4700                 } else {
4701                         abs = dB_to_coefficient (val);
4702                 }
4703 #endif
4704                 if (s->send_level_controllable (id)) {
4705                         s->send_level_controllable (id)->set_value (abs, sur->usegroup);
4706                         return 0;
4707                 }
4708         }
4709         return 0;
4710 }
4711
4712 int
4713 OSC::route_set_send_fader (int ssid, int id, float val, lo_message msg)
4714 {
4715         if (!session) {
4716                 return -1;
4717         }
4718         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4719         OSCSurface *sur = get_surface(get_address (msg));
4720         float abs;
4721         if (s) {
4722
4723                 if (id > 0) {
4724                         --id;
4725                 }
4726
4727                 if (s->send_level_controllable (id)) {
4728                         abs = s->send_level_controllable(id)->interface_to_internal (val);
4729                         s->send_level_controllable (id)->set_value (abs, sur->usegroup);
4730                         return 0;
4731                 }
4732         }
4733         return 0;
4734 }
4735
4736 int
4737 OSC::sel_sendgain (int id, float val, lo_message msg)
4738 {
4739         OSCSurface *sur = get_surface(get_address (msg));
4740         if (sur->send_page_size && (id > (int)sur->send_page_size)) {
4741                 return float_message_with_id (X_("/select/send_gain"), id, -193, sur->feedback[2], get_address (msg));
4742         }
4743         boost::shared_ptr<Stripable> s;
4744         if (sur->expand_enable) {
4745                 s = get_strip (sur->expand, get_address (msg));
4746         } else {
4747                 s = _select;
4748         }
4749         float abs;
4750         int send_id = 0;
4751         if (s) {
4752                 if (id > 0) {
4753                         send_id = id - 1;
4754                 }
4755 #ifdef MIXBUS
4756                 abs = val;
4757 #else
4758                 if (val < -192) {
4759                         abs = 0;
4760                 } else {
4761                         abs = dB_to_coefficient (val);
4762                 }
4763 #endif
4764                 if (sur->send_page_size) {
4765                         send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
4766                 }
4767                 if (s->send_level_controllable (send_id)) {
4768                         s->send_level_controllable (send_id)->set_value (abs, PBD::Controllable::NoGroup);
4769                         return 0;
4770                 }
4771         }
4772         return float_message_with_id (X_("/select/send_gain"), id, -193, sur->feedback[2], get_address (msg));
4773 }
4774
4775 int
4776 OSC::sel_sendfader (int id, float val, lo_message msg)
4777 {
4778         OSCSurface *sur = get_surface(get_address (msg));
4779         if (sur->send_page_size && (id > (int)sur->send_page_size)) {
4780                 return float_message_with_id (X_("/select/send_fader"), id, 0, sur->feedback[2], get_address (msg));
4781         }
4782         boost::shared_ptr<Stripable> s;
4783         if (sur->expand_enable) {
4784                 s = get_strip (sur->expand, get_address (msg));
4785         } else {
4786                 s = _select;
4787         }
4788         float abs;
4789         int send_id = 0;
4790         if (s) {
4791
4792                 if (id > 0) {
4793                         send_id = id - 1;
4794                 }
4795                 if (sur->send_page_size) {
4796                         send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
4797                 }
4798
4799                 if (s->send_level_controllable (send_id)) {
4800                         abs = s->send_level_controllable(send_id)->interface_to_internal (val);
4801                         s->send_level_controllable (send_id)->set_value (abs, PBD::Controllable::NoGroup);
4802                         return 0;
4803                 }
4804         }
4805         return float_message_with_id (X_("/select/send_fader"), id, 0, sur->feedback[2], get_address (msg));
4806 }
4807
4808 int
4809 OSC::route_set_send_enable (int ssid, int sid, float val, lo_message msg)
4810 {
4811         if (!session) {
4812                 return -1;
4813         }
4814         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4815         OSCSurface *sur = get_surface(get_address (msg));
4816
4817         if (s) {
4818
4819                 /* revert to zero-based counting */
4820
4821                 if (sid > 0) {
4822                         --sid;
4823                 }
4824
4825                 if (s->send_enable_controllable (sid)) {
4826                         s->send_enable_controllable (sid)->set_value (val, sur->usegroup);
4827                         return 0;
4828                 }
4829
4830                 if (s->send_level_controllable (sid)) {
4831                         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
4832                         if (!r) {
4833                                 return 0;
4834                         }
4835                         boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(sid));
4836                         if (snd) {
4837                                 if (val) {
4838                                         snd->activate();
4839                                 } else {
4840                                         snd->deactivate();
4841                                 }
4842                         }
4843                         return 0;
4844                 }
4845
4846         }
4847
4848         return -1;
4849 }
4850
4851 int
4852 OSC::sel_sendenable (int id, float val, lo_message msg)
4853 {
4854         OSCSurface *sur = get_surface(get_address (msg));
4855         if (sur->send_page_size && (id > (int)sur->send_page_size)) {
4856                 return float_message_with_id (X_("/select/send_enable"), id, 0, sur->feedback[2], get_address (msg));
4857         }
4858         boost::shared_ptr<Stripable> s;
4859         if (sur->expand_enable) {
4860                 s = get_strip (sur->expand, get_address (msg));
4861         } else {
4862                 s = _select;
4863         }
4864         int send_id = 0;
4865         if (s) {
4866                 if (id > 0) {
4867                         send_id = id - 1;
4868                 }
4869                 if (sur->send_page_size) {
4870                         send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
4871                 }
4872                 if (s->send_enable_controllable (send_id)) {
4873                         s->send_enable_controllable (send_id)->set_value (val, PBD::Controllable::NoGroup);
4874                         return 0;
4875                 }
4876                 if (s->send_level_controllable (send_id)) {
4877                         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
4878                         if (!r) {
4879                                 // should never get here
4880                                 return float_message_with_id (X_("/select/send_enable"), id, 0, sur->feedback[2], get_address (msg));
4881                         }
4882                         boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(send_id));
4883                         if (snd) {
4884                                 if (val) {
4885                                         snd->activate();
4886                                 } else {
4887                                         snd->deactivate();
4888                                 }
4889                         }
4890                         return 0;
4891                 }
4892         }
4893         return float_message_with_id (X_("/select/send_enable"), id, 0, sur->feedback[2], get_address (msg));
4894 }
4895
4896 int
4897 OSC::sel_master_send_enable (int state, lo_message msg)
4898 {
4899         OSCSurface *sur = get_surface(get_address (msg));
4900         boost::shared_ptr<Stripable> s;
4901         if (sur->expand_enable) {
4902                 s = get_strip (sur->expand, get_address (msg));
4903         } else {
4904                 s = _select;
4905         }
4906         if (s) {
4907                 if (s->master_send_enable_controllable ()) {
4908                         s->master_send_enable_controllable()->set_value (state, PBD::Controllable::NoGroup);
4909                         return 0;
4910                 }
4911         }
4912         return float_message (X_("/select/master_send_enable"), 0, get_address(msg));
4913 }
4914
4915 int
4916 OSC::select_plugin_parameter (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg) {
4917         OSCSurface *sur = get_surface(get_address (msg));
4918         int paid;
4919         uint32_t piid = sur->plugin_id;
4920         float value = 0;
4921         if (argc > 1) {
4922                 // no inline args
4923                 if (argc == 2) {
4924                         // change parameter in already selected plugin
4925                         if (types[0]  == 'f') {
4926                                 paid = (int) argv[0]->f;
4927                         } else {
4928                                 paid = argv[0]->i;
4929                         }
4930                         value = argv[1]->f;
4931                 } else if (argc == 3) {
4932                         if (types[0] == 'f') {
4933                                 piid = (int) argv[0]->f;
4934                         } else {
4935                                 piid = argv[0]->i;
4936                         }
4937                         _sel_plugin (piid, get_address (msg));
4938                         if (types[1] == 'f') {
4939                                 paid = (int) argv[1]->f;
4940                         } else {
4941                                 paid = argv[1]->i;
4942                         }
4943                         value = argv[2]->f;
4944                 } else if (argc > 3) {
4945                         PBD::warning << "OSC: Too many parameters: " << argc << endmsg;
4946                         return -1;
4947                 }
4948         } else if (argc) {
4949                 const char * par = strstr (&path[25], "/");
4950                 if (par) {
4951                         piid = atoi (&path[25]);
4952                         _sel_plugin (piid, msg);
4953                         paid = atoi (&par[1]);
4954                         value = argv[0]->f;
4955                         // we have plugin id too
4956                 } else {
4957                         // just parameter
4958                         paid = atoi (&path[25]);
4959                         value = argv[0]->f;
4960                 }
4961         } else {
4962                 PBD::warning << "OSC: Must have parameters." << endmsg;
4963                 return -1;
4964         }
4965         if (!piid || piid > sur->plugins.size ()) {
4966                 return float_message_with_id (X_("/select/plugin/parameter"), paid, 0, sur->feedback[2], get_address (msg));
4967         }
4968         if (sur->plug_page_size && (paid > (int)sur->plug_page_size)) {
4969                 return float_message_with_id (X_("/select/plugin/parameter"), paid, 0, sur->feedback[2], get_address (msg));
4970         }
4971         boost::shared_ptr<Stripable> s = sur->select;
4972         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
4973         if (!r) {
4974                 return 1;
4975         }
4976
4977         boost::shared_ptr<Processor> proc = r->nth_plugin (sur->plugins[sur->plugin_id - 1]);
4978         boost::shared_ptr<PluginInsert> pi;
4979         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(proc))) {
4980                 return 1;
4981         }
4982         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
4983         // paid is paged parameter convert to absolute
4984         int parid = paid + (int)sur->plug_page - 1;
4985         if (parid > (int) sur->plug_params.size ()) {
4986                 if (sur->feedback[13]) {
4987                         float_message_with_id (X_("/select/plugin/parameter"), paid, 0, sur->feedback[2], get_address (msg));
4988                 }
4989                 return 0;
4990         }
4991
4992         bool ok = false;
4993         uint32_t controlid = pip->nth_parameter(sur->plug_params[parid - 1], ok);
4994         if (!ok) {
4995                 return 1;
4996         }
4997         ParameterDescriptor pd;
4998         pip->get_parameter_descriptor(controlid, pd);
4999         if ( pip->parameter_is_input(controlid) || pip->parameter_is_control(controlid) ) {
5000                 boost::shared_ptr<AutomationControl> c = pi->automation_control(Evoral::Parameter(PluginAutomation, 0, controlid));
5001                 if (c) {
5002                         if (pd.integer_step && pd.upper == 1) {
5003                                 if (c->get_value () && value < 1.0) {
5004                                         c->set_value (0, PBD::Controllable::NoGroup);
5005                                 } else if (!c->get_value () && value) {
5006                                         c->set_value (1, PBD::Controllable::NoGroup);
5007                                 }
5008                         } else {
5009                                 c->set_value (c->interface_to_internal (value), PBD::Controllable::NoGroup);
5010                         }
5011                         return 0;
5012                 }
5013         }
5014         return 1;
5015 }
5016
5017 int
5018 OSC::sel_plugin_activate (float state, lo_message msg)
5019 {
5020         if (!session) {
5021                 return -1;
5022         }
5023         OSCSurface *sur = get_surface(get_address (msg));
5024         if (sur->plugins.size() > 0) {
5025                 boost::shared_ptr<Stripable> s = sur->select;
5026
5027                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5028
5029                 if (r) {
5030                         boost::shared_ptr<Processor> redi=r->nth_plugin (sur->plugins[sur->plugin_id -1]);
5031                         if (redi) {
5032                                 boost::shared_ptr<PluginInsert> pi;
5033                                 if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5034                                         if(state > 0) {
5035                                                 pi->activate();
5036                                         } else {
5037                                                 pi->deactivate();
5038                                         }
5039                                         return 0;
5040                                 }
5041                         }
5042                 }
5043         }
5044         float_message (X_("/select/plugin/activate"), 0, get_address (msg));
5045         PBD::warning << "OSC: Select has no Plugin." << endmsg;
5046         return 0;
5047 }
5048
5049 int
5050 OSC::route_plugin_list (int ssid, lo_message msg) {
5051         if (!session) {
5052                 return -1;
5053         }
5054
5055         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
5056
5057         if (!r) {
5058                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5059                 return -1;
5060         }
5061         int piid = 0;
5062
5063         lo_message reply = lo_message_new ();
5064         lo_message_add_int32 (reply, ssid);
5065
5066
5067         for (;;) {
5068                 boost::shared_ptr<Processor> redi = r->nth_plugin(piid);
5069                 if ( !redi ) {
5070                         break;
5071                 }
5072
5073                 boost::shared_ptr<PluginInsert> pi;
5074
5075                 if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5076                         PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5077                         continue;
5078                 }
5079                 lo_message_add_int32 (reply, piid + 1);
5080
5081                 boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5082                 lo_message_add_string (reply, pip->name());
5083                 lo_message_add_int32(reply, redi->enabled() ? 1 : 0);
5084
5085                 piid++;
5086         }
5087
5088         lo_send_message (get_address (msg), X_("/strip/plugin/list"), reply);
5089         lo_message_free (reply);
5090         return 0;
5091 }
5092
5093 int
5094 OSC::route_plugin_descriptor (int ssid, int piid, lo_message msg) {
5095         if (!session) {
5096                 return -1;
5097         }
5098
5099         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
5100
5101         if (!r) {
5102                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5103                 return -1;
5104         }
5105
5106         boost::shared_ptr<Processor> redi = r->nth_plugin(piid - 1);
5107
5108         if (!redi) {
5109                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5110                 return -1;
5111         }
5112
5113         boost::shared_ptr<PluginInsert> pi;
5114
5115         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5116                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5117                 return -1;
5118         }
5119
5120         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5121         bool ok = false;
5122
5123         for ( uint32_t ppi = 0; ppi < pip->parameter_count(); ppi++) {
5124
5125                 uint32_t controlid = pip->nth_parameter(ppi, ok);
5126                 if (!ok) {
5127                         continue;
5128                 }
5129                 boost::shared_ptr<AutomationControl> c = pi->automation_control(Evoral::Parameter(PluginAutomation, 0, controlid));
5130
5131                 lo_message reply = lo_message_new();
5132                 lo_message_add_int32 (reply, ssid);
5133                 lo_message_add_int32 (reply, piid);
5134
5135                 lo_message_add_int32 (reply, ppi + 1);
5136                 ParameterDescriptor pd;
5137                 pi->plugin()->get_parameter_descriptor(controlid, pd);
5138                 lo_message_add_string (reply, pd.label.c_str());
5139
5140                 // I've combined those binary descriptor parts in a bit-field to reduce lilo message elements
5141                 int flags = 0;
5142                 flags |= pd.enumeration ? 1 : 0;
5143                 flags |= pd.integer_step ? 2 : 0;
5144                 flags |= pd.logarithmic ? 4 : 0;
5145                 flags |= pd.sr_dependent ? 32 : 0;
5146                 flags |= pd.toggled ? 64 : 0;
5147                 flags |= pip->parameter_is_input(controlid) ? 0x80 : 0;
5148
5149                 std::string param_desc = pi->plugin()->describe_parameter(Evoral::Parameter(PluginAutomation, 0, controlid));
5150                 flags |= (param_desc == X_("hidden")) ? 0x100 : 0;
5151                 lo_message_add_int32 (reply, flags);
5152
5153                 switch(pd.datatype) {
5154                         case ARDOUR::Variant::BEATS:
5155                                 lo_message_add_string(reply, _("BEATS"));
5156                                 break;
5157                         case ARDOUR::Variant::BOOL:
5158                                 lo_message_add_string(reply, _("BOOL"));
5159                                 break;
5160                         case ARDOUR::Variant::DOUBLE:
5161                                 lo_message_add_string(reply, _("DOUBLE"));
5162                                 break;
5163                         case ARDOUR::Variant::FLOAT:
5164                                 lo_message_add_string(reply, _("FLOAT"));
5165                                 break;
5166                         case ARDOUR::Variant::INT:
5167                                 lo_message_add_string(reply, _("INT"));
5168                                 break;
5169                         case ARDOUR::Variant::LONG:
5170                                 lo_message_add_string(reply, _("LONG"));
5171                                 break;
5172                         case ARDOUR::Variant::NOTHING:
5173                                 lo_message_add_string(reply, _("NOTHING"));
5174                                 break;
5175                         case ARDOUR::Variant::PATH:
5176                                 lo_message_add_string(reply, _("PATH"));
5177                                 break;
5178                         case ARDOUR::Variant::STRING:
5179                                 lo_message_add_string(reply, _("STRING"));
5180                                 break;
5181                         case ARDOUR::Variant::URI:
5182                                 lo_message_add_string(reply, _("URI"));
5183                                 break;
5184                         default:
5185                                 lo_message_add_string(reply, _("UNKNOWN"));
5186                                 break;
5187                 }
5188                 lo_message_add_float (reply, pd.lower);
5189                 lo_message_add_float (reply, pd.upper);
5190                 lo_message_add_string (reply, pd.print_fmt.c_str());
5191                 if ( pd.scale_points ) {
5192                         lo_message_add_int32 (reply, pd.scale_points->size());
5193                         for ( ARDOUR::ScalePoints::const_iterator i = pd.scale_points->begin(); i != pd.scale_points->end(); ++i) {
5194                                 lo_message_add_float (reply, i->second);
5195                                 lo_message_add_string (reply, ((std::string)i->first).c_str());
5196                         }
5197                 }
5198                 else {
5199                         lo_message_add_int32 (reply, 0);
5200                 }
5201                 if ( c ) {
5202                         lo_message_add_double (reply, c->get_value());
5203                 }
5204                 else {
5205                         lo_message_add_double (reply, 0);
5206                 }
5207
5208                 lo_send_message (get_address (msg), X_("/strip/plugin/descriptor"), reply);
5209                 lo_message_free (reply);
5210         }
5211
5212         lo_message reply = lo_message_new ();
5213         lo_message_add_int32 (reply, ssid);
5214         lo_message_add_int32 (reply, piid);
5215         lo_send_message (get_address (msg), X_("/strip/plugin/descriptor_end"), reply);
5216         lo_message_free (reply);
5217
5218         return 0;
5219 }
5220
5221 int
5222 OSC::route_plugin_reset (int ssid, int piid, lo_message msg) {
5223         if (!session) {
5224                 return -1;
5225         }
5226
5227         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
5228
5229         if (!r) {
5230                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5231                 return -1;
5232         }
5233
5234         boost::shared_ptr<Processor> redi = r->nth_plugin(piid - 1);
5235
5236         if (!redi) {
5237                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5238                 return -1;
5239         }
5240
5241         boost::shared_ptr<PluginInsert> pi;
5242
5243         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5244                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5245                 return -1;
5246         }
5247
5248         pi->reset_parameters_to_default ();
5249
5250         return 0;
5251 }
5252
5253 int
5254 OSC::route_plugin_parameter (int ssid, int piid, int par, float val, lo_message msg)
5255 {
5256         if (!session)
5257                 return -1;
5258         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
5259
5260         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5261
5262         if (!r) {
5263                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5264                 return -1;
5265         }
5266
5267         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
5268
5269         if (!redi) {
5270                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5271                 return -1;
5272         }
5273
5274         boost::shared_ptr<PluginInsert> pi;
5275
5276         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5277                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5278                 return -1;
5279         }
5280
5281         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5282         bool ok=false;
5283
5284         uint32_t controlid = pip->nth_parameter (par - 1,ok);
5285
5286         if (!ok) {
5287                 PBD::error << "OSC: Cannot find parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "'" << endmsg;
5288                 return -1;
5289         }
5290
5291         if (!pip->parameter_is_input(controlid)) {
5292                 PBD::error << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "' is not a control input" << endmsg;
5293                 return -1;
5294         }
5295
5296         ParameterDescriptor pd;
5297         pi->plugin()->get_parameter_descriptor (controlid,pd);
5298
5299         if (val >= pd.lower && val <= pd.upper) {
5300
5301                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
5302                 // cerr << "parameter:" << redi->describe_parameter(controlid) << " val:" << val << "\n";
5303                 c->set_value (val, PBD::Controllable::NoGroup);
5304         } else {
5305                 PBD::warning << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "' is out of range" << endmsg;
5306                 PBD::info << "OSC: Valid range min=" << pd.lower << " max=" << pd.upper << endmsg;
5307         }
5308
5309         return 0;
5310 }
5311
5312 //prints to cerr only
5313 int
5314 OSC::route_plugin_parameter_print (int ssid, int piid, int par, lo_message msg)
5315 {
5316         if (!session) {
5317                 return -1;
5318         }
5319         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
5320
5321         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5322
5323         if (!r) {
5324                 return -1;
5325         }
5326
5327         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
5328
5329         if (!redi) {
5330                 return -1;
5331         }
5332
5333         boost::shared_ptr<PluginInsert> pi;
5334
5335         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5336                 return -1;
5337         }
5338
5339         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5340         bool ok=false;
5341
5342         uint32_t controlid = pip->nth_parameter (par - 1,ok);
5343
5344         if (!ok) {
5345                 return -1;
5346         }
5347
5348         ParameterDescriptor pd;
5349
5350         if (pi->plugin()->get_parameter_descriptor (controlid, pd) == 0) {
5351                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
5352
5353                 cerr << "parameter:     " << pd.label  << "\n";
5354                 if (c) {
5355                         cerr << "current value: " << c->get_value () << "\n";
5356                 } else {
5357                         cerr << "current value not available, control does not exist\n";
5358                 }
5359                 cerr << "lower value:   " << pd.lower << "\n";
5360                 cerr << "upper value:   " << pd.upper << "\n";
5361         }
5362
5363         return 0;
5364 }
5365
5366 int
5367 OSC::route_plugin_activate (int ssid, int piid, lo_message msg)
5368 {
5369         if (!session)
5370                 return -1;
5371         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
5372
5373         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5374
5375         if (!r) {
5376                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5377                 return -1;
5378         }
5379
5380         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
5381
5382         if (!redi) {
5383                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5384                 return -1;
5385         }
5386
5387         boost::shared_ptr<PluginInsert> pi;
5388
5389         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5390                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5391                 return -1;
5392         }
5393
5394         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5395         pi->activate();
5396
5397         return 0;
5398 }
5399
5400 int
5401 OSC::route_plugin_deactivate (int ssid, int piid, lo_message msg)
5402 {
5403         if (!session)
5404                 return -1;
5405         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
5406
5407         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5408
5409         if (!r) {
5410                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5411                 return -1;
5412         }
5413
5414         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
5415
5416         if (!redi) {
5417                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5418                 return -1;
5419         }
5420
5421         boost::shared_ptr<PluginInsert> pi;
5422
5423         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5424                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5425                 return -1;
5426         }
5427
5428         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5429         pi->deactivate();
5430
5431         return 0;
5432 }
5433
5434 // select
5435
5436 int
5437 OSC::sel_pan_elevation (float val, lo_message msg)
5438 {
5439         OSCSurface *sur = get_surface(get_address (msg));
5440         boost::shared_ptr<Stripable> s;
5441         if (sur->expand_enable) {
5442                 s = get_strip (sur->expand, get_address (msg));
5443         } else {
5444                 s = _select;
5445         }
5446         if (s) {
5447                 if (s->pan_elevation_control()) {
5448                         s->pan_elevation_control()->set_value (s->pan_elevation_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
5449                         return 0;
5450                 }
5451         }
5452         return float_message(X_("/select/pan_elevation_position"), 0, get_address (msg));
5453 }
5454
5455 int
5456 OSC::sel_pan_frontback (float val, lo_message msg)
5457 {
5458         OSCSurface *sur = get_surface(get_address (msg));
5459         boost::shared_ptr<Stripable> s;
5460         if (sur->expand_enable) {
5461                 s = get_strip (sur->expand, get_address (msg));
5462         } else {
5463                 s = _select;
5464         }
5465         if (s) {
5466                 if (s->pan_frontback_control()) {
5467                         s->pan_frontback_control()->set_value (s->pan_frontback_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
5468                         return 0;
5469                 }
5470         }
5471         return float_message(X_("/select/pan_frontback_position"), 0.5, get_address (msg));
5472 }
5473
5474 int
5475 OSC::sel_pan_lfe (float val, lo_message msg)
5476 {
5477         OSCSurface *sur = get_surface(get_address (msg));
5478         boost::shared_ptr<Stripable> s;
5479         if (sur->expand_enable) {
5480                 s = get_strip (sur->expand, get_address (msg));
5481         } else {
5482                 s = _select;
5483         }
5484         if (s) {
5485                 if (s->pan_lfe_control()) {
5486                         s->pan_lfe_control()->set_value (s->pan_lfe_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
5487                         return 0;
5488                 }
5489         }
5490         return float_message(X_("/select/pan_lfe_control"), 0, get_address (msg));
5491 }
5492
5493 // compressor control
5494 int
5495 OSC::sel_comp_enable (float val, lo_message msg)
5496 {
5497         OSCSurface *sur = get_surface(get_address (msg));
5498         boost::shared_ptr<Stripable> s;
5499         if (sur->expand_enable) {
5500                 s = get_strip (sur->expand, get_address (msg));
5501         } else {
5502                 s = _select;
5503         }
5504         if (s) {
5505                 if (s->comp_enable_controllable()) {
5506                         s->comp_enable_controllable()->set_value (s->comp_enable_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5507                         return 0;
5508                 }
5509         }
5510         return float_message(X_("/select/comp_enable"), 0, get_address (msg));
5511 }
5512
5513 int
5514 OSC::sel_comp_threshold (float val, lo_message msg)
5515 {
5516         OSCSurface *sur = get_surface(get_address (msg));
5517         boost::shared_ptr<Stripable> s;
5518         if (sur->expand_enable) {
5519                 s = get_strip (sur->expand, get_address (msg));
5520         } else {
5521                 s = _select;
5522         }
5523         if (s) {
5524                 if (s->comp_threshold_controllable()) {
5525                         s->comp_threshold_controllable()->set_value (s->comp_threshold_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5526                         return 0;
5527                 }
5528         }
5529         return float_message(X_("/select/comp_threshold"), 0, get_address (msg));
5530 }
5531
5532 int
5533 OSC::sel_comp_speed (float val, lo_message msg)
5534 {
5535         OSCSurface *sur = get_surface(get_address (msg));
5536         boost::shared_ptr<Stripable> s;
5537         if (sur->expand_enable) {
5538                 s = get_strip (sur->expand, get_address (msg));
5539         } else {
5540                 s = _select;
5541         }
5542         if (s) {
5543                 if (s->comp_speed_controllable()) {
5544                         s->comp_speed_controllable()->set_value (s->comp_speed_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5545                         return 0;
5546                 }
5547         }
5548         return float_message(X_("/select/comp_speed"), 0, get_address (msg));
5549 }
5550
5551 int
5552 OSC::sel_comp_mode (float val, lo_message msg)
5553 {
5554         OSCSurface *sur = get_surface(get_address (msg));
5555         boost::shared_ptr<Stripable> s;
5556         if (sur->expand_enable) {
5557                 s = get_strip (sur->expand, get_address (msg));
5558         } else {
5559                 s = _select;
5560         }
5561         if (s) {
5562                 if (s->comp_mode_controllable()) {
5563                         s->comp_mode_controllable()->set_value (s->comp_mode_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5564                         return 0;
5565                 }
5566         }
5567         return float_message(X_("/select/comp_mode"), 0, get_address (msg));
5568 }
5569
5570 int
5571 OSC::sel_comp_makeup (float val, lo_message msg)
5572 {
5573         OSCSurface *sur = get_surface(get_address (msg));
5574         boost::shared_ptr<Stripable> s;
5575         if (sur->expand_enable) {
5576                 s = get_strip (sur->expand, get_address (msg));
5577         } else {
5578                 s = _select;
5579         }
5580         if (s) {
5581                 if (s->comp_makeup_controllable()) {
5582                         s->comp_makeup_controllable()->set_value (s->comp_makeup_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5583                         return 0;
5584                 }
5585         }
5586         return float_message(X_("/select/comp_makeup"), 0, get_address (msg));
5587 }
5588
5589 // EQ control
5590
5591 int
5592 OSC::sel_eq_enable (float val, lo_message msg)
5593 {
5594         OSCSurface *sur = get_surface(get_address (msg));
5595         boost::shared_ptr<Stripable> s;
5596         if (sur->expand_enable) {
5597                 s = get_strip (sur->expand, get_address (msg));
5598         } else {
5599                 s = _select;
5600         }
5601         if (s) {
5602                 if (s->eq_enable_controllable()) {
5603                         s->eq_enable_controllable()->set_value (s->eq_enable_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5604                         return 0;
5605                 }
5606         }
5607         return float_message(X_("/select/eq_enable"), 0, get_address (msg));
5608 }
5609
5610 int
5611 OSC::sel_eq_hpf_freq (float val, lo_message msg)
5612 {
5613         OSCSurface *sur = get_surface(get_address (msg));
5614         boost::shared_ptr<Stripable> s;
5615         if (sur->expand_enable) {
5616                 s = get_strip (sur->expand, get_address (msg));
5617         } else {
5618                 s = _select;
5619         }
5620         if (s) {
5621                 if (s->filter_freq_controllable(true)) {
5622                         s->filter_freq_controllable(true)->set_value (s->filter_freq_controllable(true)->interface_to_internal (val), PBD::Controllable::NoGroup);
5623                         return 0;
5624                 }
5625         }
5626         return float_message(X_("/select/eq_hpf/freq"), 0, get_address (msg));
5627 }
5628
5629 int
5630 OSC::sel_eq_lpf_freq (float val, lo_message msg)
5631 {
5632         OSCSurface *sur = get_surface(get_address (msg));
5633         boost::shared_ptr<Stripable> s;
5634         if (sur->expand_enable) {
5635                 s = get_strip (sur->expand, get_address (msg));
5636         } else {
5637                 s = _select;
5638         }
5639         if (s) {
5640                 if (s->filter_freq_controllable(false)) {
5641                         s->filter_freq_controllable(false)->set_value (s->filter_freq_controllable(false)->interface_to_internal (val), PBD::Controllable::NoGroup);
5642                         return 0;
5643                 }
5644         }
5645         return float_message(X_("/select/eq_lpf/freq"), 0, get_address (msg));
5646 }
5647
5648 int
5649 OSC::sel_eq_hpf_enable (float val, lo_message msg)
5650 {
5651         OSCSurface *sur = get_surface(get_address (msg));
5652         boost::shared_ptr<Stripable> s;
5653         if (sur->expand_enable) {
5654                 s = get_strip (sur->expand, get_address (msg));
5655         } else {
5656                 s = _select;
5657         }
5658         if (s) {
5659                 if (s->filter_enable_controllable(true)) {
5660                         s->filter_enable_controllable(true)->set_value (s->filter_enable_controllable(true)->interface_to_internal (val), PBD::Controllable::NoGroup);
5661                         return 0;
5662                 }
5663         }
5664         return float_message(X_("/select/eq_hpf/enable"), 0, get_address (msg));
5665 }
5666
5667 int
5668 OSC::sel_eq_lpf_enable (float val, lo_message msg)
5669 {
5670         OSCSurface *sur = get_surface(get_address (msg));
5671         boost::shared_ptr<Stripable> s;
5672         if (sur->expand_enable) {
5673                 s = get_strip (sur->expand, get_address (msg));
5674         } else {
5675                 s = _select;
5676         }
5677         if (s) {
5678                 if (s->filter_enable_controllable(false)) {
5679                         s->filter_enable_controllable(false)->set_value (s->filter_enable_controllable(false)->interface_to_internal (val), PBD::Controllable::NoGroup);
5680                         return 0;
5681                 }
5682         }
5683         return float_message(X_("/select/eq_lpf/enable"), 0, get_address (msg));
5684 }
5685
5686 int
5687 OSC::sel_eq_hpf_slope (float val, lo_message msg)
5688 {
5689         OSCSurface *sur = get_surface(get_address (msg));
5690         boost::shared_ptr<Stripable> s;
5691         if (sur->expand_enable) {
5692                 s = get_strip (sur->expand, get_address (msg));
5693         } else {
5694                 s = _select;
5695         }
5696         if (s) {
5697                 if (s->filter_slope_controllable(true)) {
5698                         s->filter_slope_controllable(true)->set_value (s->filter_slope_controllable(true)->interface_to_internal (val), PBD::Controllable::NoGroup);
5699                         return 0;
5700                 }
5701         }
5702         return float_message(X_("/select/eq_hpf/slope"), 0, get_address (msg));
5703 }
5704
5705 int
5706 OSC::sel_eq_lpf_slope (float val, lo_message msg)
5707 {
5708         OSCSurface *sur = get_surface(get_address (msg));
5709         boost::shared_ptr<Stripable> s;
5710         if (sur->expand_enable) {
5711                 s = get_strip (sur->expand, get_address (msg));
5712         } else {
5713                 s = _select;
5714         }
5715         if (s) {
5716                 if (s->filter_slope_controllable(false)) {
5717                         s->filter_slope_controllable(false)->set_value (s->filter_slope_controllable(false)->interface_to_internal (val), PBD::Controllable::NoGroup);
5718                         return 0;
5719                 }
5720         }
5721         return float_message(X_("/select/eq_lpf/slope"), 0, get_address (msg));
5722 }
5723
5724 int
5725 OSC::sel_eq_gain (int id, float val, lo_message msg)
5726 {
5727         OSCSurface *sur = get_surface(get_address (msg));
5728         boost::shared_ptr<Stripable> s;
5729         if (sur->expand_enable) {
5730                 s = get_strip (sur->expand, get_address (msg));
5731         } else {
5732                 s = _select;
5733         }
5734         if (s) {
5735                 if (id > 0) {
5736                         --id;
5737                 }
5738                 if (s->eq_gain_controllable (id)) {
5739                         s->eq_gain_controllable (id)->set_value (s->eq_gain_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
5740                         return 0;
5741                 }
5742         }
5743         return float_message_with_id (X_("/select/eq_gain"), id + 1, 0, sur->feedback[2], get_address (msg));
5744 }
5745
5746 int
5747 OSC::sel_eq_freq (int id, float val, lo_message msg)
5748 {
5749         OSCSurface *sur = get_surface(get_address (msg));
5750         boost::shared_ptr<Stripable> s;
5751         if (sur->expand_enable) {
5752                 s = get_strip (sur->expand, get_address (msg));
5753         } else {
5754                 s = _select;
5755         }
5756         if (s) {
5757                 if (id > 0) {
5758                         --id;
5759                 }
5760                 if (s->eq_freq_controllable (id)) {
5761                         s->eq_freq_controllable (id)->set_value (s->eq_freq_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
5762                         return 0;
5763                 }
5764         }
5765         return float_message_with_id (X_("/select/eq_freq"), id + 1, 0, sur->feedback[2], get_address (msg));
5766 }
5767
5768 int
5769 OSC::sel_eq_q (int id, float val, lo_message msg)
5770 {
5771         OSCSurface *sur = get_surface(get_address (msg));
5772         boost::shared_ptr<Stripable> s;
5773         if (sur->expand_enable) {
5774                 s = get_strip (sur->expand, get_address (msg));
5775         } else {
5776                 s = _select;
5777         }
5778         if (s) {
5779                 if (id > 0) {
5780                         --id;
5781                 }
5782                 if (s->eq_q_controllable (id)) {
5783                         s->eq_q_controllable (id)->set_value (s->eq_q_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
5784                         return 0;
5785                 }
5786         }
5787         return float_message_with_id (X_("/select/eq_q"), id + 1, 0, sur->feedback[2], get_address (msg));
5788 }
5789
5790 int
5791 OSC::sel_eq_shape (int id, float val, lo_message msg)
5792 {
5793         OSCSurface *sur = get_surface(get_address (msg));
5794         boost::shared_ptr<Stripable> s;
5795         if (sur->expand_enable) {
5796                 s = get_strip (sur->expand, get_address (msg));
5797         } else {
5798                 s = _select;
5799         }
5800         if (s) {
5801                 if (id > 0) {
5802                         --id;
5803                 }
5804                 if (s->eq_shape_controllable (id)) {
5805                         s->eq_shape_controllable (id)->set_value (s->eq_shape_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
5806                         return 0;
5807                 }
5808         }
5809         return float_message_with_id (X_("/select/eq_shape"), id + 1, 0, sur->feedback[2], get_address (msg));
5810 }
5811
5812 // timer callbacks
5813 bool
5814 OSC::periodic (void)
5815 {
5816         if (observer_busy) {
5817                 return true;
5818         }
5819         if (!tick) {
5820                 Glib::usleep(100); // let flurry of signals subside
5821                 if (global_init) {
5822                         for (uint32_t it = 0; it < _surface.size(); it++) {
5823                                 OSCSurface* sur = &_surface[it];
5824                                 global_feedback (sur);
5825                         }
5826                         global_init = false;
5827                         tick = true;
5828                 }
5829                 if (bank_dirty) {
5830                         _recalcbanks ();
5831                         bank_dirty = false;
5832                         tick = true;
5833                 }
5834                 return true;
5835         }
5836
5837         if (scrub_speed != 0) {
5838                 // for those jog wheels that don't have 0 on release (touch), time out.
5839                 int64_t now = ARDOUR::get_microseconds ();
5840                 int64_t diff = now - scrub_time;
5841                 if (diff > 120000) {
5842                         scrub_speed = 0;
5843                         session->request_transport_speed (0);
5844                         // locate to the place PH was at last tick
5845                         session->request_locate (scrub_place, false);
5846                 }
5847         }
5848         for (uint32_t it = 0; it < _surface.size(); it++) {
5849                 OSCSurface* sur = &_surface[it];
5850                 OSCSelectObserver* so;
5851                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
5852                         so->tick ();
5853                 }
5854                 OSCCueObserver* co;
5855                 if ((co = dynamic_cast<OSCCueObserver*>(sur->cue_obs)) != 0) {
5856                         co->tick ();
5857                 }
5858                 OSCGlobalObserver* go;
5859                 if ((go = dynamic_cast<OSCGlobalObserver*>(sur->global_obs)) != 0) {
5860                         go->tick ();
5861                 }
5862                 for (uint32_t i = 0; i < sur->observers.size(); i++) {
5863                         OSCRouteObserver* ro;
5864                         if ((ro = dynamic_cast<OSCRouteObserver*>(sur->observers[i])) != 0) {
5865                                 ro->tick ();
5866                         }
5867                 }
5868
5869         }
5870         for (FakeTouchMap::iterator x = _touch_timeout.begin(); x != _touch_timeout.end();) {
5871                 _touch_timeout[(*x).first] = (*x).second - 1;
5872                 if (!(*x).second) {
5873                         boost::shared_ptr<ARDOUR::AutomationControl> ctrl = (*x).first;
5874                         // turn touch off
5875                         ctrl->stop_touch (ctrl->session().transport_sample());
5876                         _touch_timeout.erase (x++);
5877                 } else {
5878                         x++;
5879                 }
5880         }
5881         return true;
5882 }
5883
5884 XMLNode&
5885 OSC::get_state ()
5886 {
5887         XMLNode& node (ControlProtocol::get_state());
5888         node.set_property (X_("debugmode"), (int32_t) _debugmode); // TODO: enum2str
5889         node.set_property (X_("address-only"), address_only);
5890         node.set_property (X_("remote-port"), remote_port);
5891         node.set_property (X_("banksize"), default_banksize);
5892         node.set_property (X_("striptypes"), default_strip);
5893         node.set_property (X_("feedback"), default_feedback);
5894         node.set_property (X_("gainmode"), default_gainmode);
5895         node.set_property (X_("send-page-size"), default_send_size);
5896         node.set_property (X_("plug-page-size"), default_plugin_size);
5897         return node;
5898 }
5899
5900 int
5901 OSC::set_state (const XMLNode& node, int version)
5902 {
5903         if (ControlProtocol::set_state (node, version)) {
5904                 return -1;
5905         }
5906         int32_t debugmode;
5907         if (node.get_property (X_("debugmode"), debugmode)) {
5908                 _debugmode = OSCDebugMode (debugmode);
5909         }
5910
5911         node.get_property (X_("address-only"), address_only);
5912         node.get_property (X_("remote-port"), remote_port);
5913         node.get_property (X_("banksize"), default_banksize);
5914         node.get_property (X_("striptypes"), default_strip);
5915         node.get_property (X_("feedback"), default_feedback);
5916         node.get_property (X_("gainmode"), default_gainmode);
5917         node.get_property (X_("send-page-size"), default_send_size);
5918         node.get_property (X_("plugin-page-size"), default_plugin_size);
5919
5920         global_init = true;
5921         tick = false;
5922
5923         return 0;
5924 }
5925
5926 // predicate for sort call in get_sorted_stripables
5927 struct StripableByPresentationOrder
5928 {
5929         bool operator () (const boost::shared_ptr<Stripable> & a, const boost::shared_ptr<Stripable> & b) const
5930         {
5931                 return a->presentation_info().order() < b->presentation_info().order();
5932         }
5933
5934         bool operator () (const Stripable & a, const Stripable & b) const
5935         {
5936                 return a.presentation_info().order() < b.presentation_info().order();
5937         }
5938
5939         bool operator () (const Stripable * a, const Stripable * b) const
5940         {
5941                 return a->presentation_info().order() < b->presentation_info().order();
5942         }
5943 };
5944
5945 OSC::Sorted
5946 OSC::get_sorted_stripables(std::bitset<32> types, bool cue, uint32_t custom, Sorted my_list)
5947 {
5948         Sorted sorted;
5949         StripableList stripables;
5950         StripableList custom_list;
5951
5952         // fetch all stripables
5953         session->get_stripables (stripables);
5954         if (custom) {
5955                 uint32_t nstps = my_list.size ();
5956                 // check each custom strip to see if it still exists
5957                 boost::shared_ptr<Stripable> s;
5958                 for (uint32_t i = 0; i < nstps; i++) {
5959                         bool exists = false;
5960                         s = my_list[i];
5961                         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
5962                                 boost::shared_ptr<Stripable> sl = *it;
5963                                 if (s == sl) {
5964                                         exists = true;
5965                                         break;
5966                                 }
5967                         }
5968                         if(!exists) {
5969                                 my_list[i] = boost::shared_ptr<Stripable>();
5970                         } else {
5971                                 custom_list.push_back (s);
5972                         }
5973                 }
5974                 if (custom == 1) {
5975                         return my_list;
5976                 } else {
5977                         stripables = custom_list;
5978                 }
5979         }
5980         // Look for stripables that match bit in sur->strip_types
5981         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
5982
5983                 boost::shared_ptr<Stripable> s = *it;
5984                 if (!s) {
5985                         break;
5986                 }
5987                 if (custom == 2) {
5988                         // banking off use all valid custom strips
5989                         sorted.push_back (s);
5990                 } else
5991                 if ((!cue) && (!types[9]) && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
5992                         // do nothing... skip it
5993                 } else if (types[8] && (s->is_selected())) {
5994                         sorted.push_back (s);
5995                 } else if (types[9] && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
5996                         sorted.push_back (s);
5997                 } else if (s->is_master() || s->is_monitor() || s->is_auditioner()) {
5998                         // do nothing for these either (we add them later)
5999                 } else {
6000                         if (types[0] && boost::dynamic_pointer_cast<AudioTrack>(s)) {
6001                                 sorted.push_back (s);
6002                         } else if (types[1] && boost::dynamic_pointer_cast<MidiTrack>(s)) {
6003                                 sorted.push_back (s);
6004                         } else if (types[4] && boost::dynamic_pointer_cast<VCA>(s)) {
6005                                 sorted.push_back (s);
6006                         } else
6007 #ifdef MIXBUS
6008                         if (types[2] && Profile->get_mixbus() && s->mixbus()) {
6009                                 sorted.push_back (s);
6010                         } else
6011                         if (types[7] && boost::dynamic_pointer_cast<Route>(s) && !boost::dynamic_pointer_cast<Track>(s)) {
6012                                 if (Profile->get_mixbus() && !s->mixbus()) {
6013                                         sorted.push_back (s);
6014                                 }
6015                         } else
6016 #endif
6017                         if ((types[2] || types[3] || types[7]) && boost::dynamic_pointer_cast<Route>(s) && !boost::dynamic_pointer_cast<Track>(s)) {
6018                                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
6019                                 if (!(s->presentation_info().flags() & PresentationInfo::MidiBus)) {
6020                                         // note some older sessions will show midibuses as busses
6021                                         if (r->direct_feeds_according_to_reality (session->master_out())) {
6022                                                 // this is a bus
6023                                                 if (types[2]) {
6024                                                         sorted.push_back (s);
6025                                                 }
6026                                         } else {
6027                                                 // this is an Aux out
6028                                                 if (types[7]) {
6029                                                         sorted.push_back (s);
6030                                                 }
6031                                         }
6032                                 } else if (types[3]) {
6033                                                 sorted.push_back (s);
6034                                 }
6035                         }
6036                 }
6037         }
6038         if (!custom || (custom & 0x2)) {
6039                 sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
6040         }
6041         if (!custom) {
6042                 // Master/Monitor might be anywhere... we put them at the end - Sorry ;)
6043                 if (types[5]) {
6044                         sorted.push_back (session->master_out());
6045                 }
6046                 if (types[6]) {
6047                         if (session->monitor_out()) {
6048                                 sorted.push_back (session->monitor_out());
6049                         }
6050                 }
6051         }
6052         return sorted;
6053 }
6054
6055 int
6056 OSC::cue_parse (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
6057 {
6058         OSCSurface *s = get_surface(get_address (msg), true);
6059         s->bank_size = 0;
6060         float value = 0;
6061         if (argc == 1) {
6062                 if (types[0] == 'f') {
6063                         value = argv[0]->f;
6064                 } else if (types[0] == 'i') {
6065                         value = (float) argv[0]->i;
6066                 }
6067         }
6068         int ret = 1; /* unhandled */
6069         if (!strncmp (path, X_("/cue/aux"), 8)) {
6070                 // set our Aux bus
6071                 if (argc) {
6072                         if (value) {
6073                                 ret = cue_set ((uint32_t) value, msg);
6074                         } else {
6075                                 ret = 0;
6076                         }
6077                 }
6078         }
6079         else if (!strncmp (path, X_("/cue/connect"), 12)) {
6080                 // Connect to default Aux bus
6081                 if ((!argc) || argv[0]->f || argv[0]->i) {
6082                         ret = cue_set (1, msg);
6083                 } else {
6084                         ret = 0;
6085                 }
6086         }
6087         else if (!strncmp (path, X_("/cue/next_aux"), 13)) {
6088                 // switch to next Aux bus
6089                 if ((!argc) || argv[0]->f || argv[0]->i) {
6090                         ret = cue_next (msg);
6091                 } else {
6092                         ret = 0;
6093                 }
6094         }
6095         else if (!strncmp (path, X_("/cue/previous_aux"), 17)) {
6096                 // switch to previous Aux bus
6097                 if ((!argc) || argv[0]->f || argv[0]->i) {
6098                         ret = cue_previous (msg);
6099                 } else {
6100                         ret = 0;
6101                 }
6102         }
6103         else if (!strncmp (path, X_("/cue/send/fader/"), 16) && strlen (path) > 16) {
6104                 if (argc == 1) {
6105                         int id = atoi (&path[16]);
6106                         ret = cue_send_fader (id, value, msg);
6107                 }
6108         }
6109         else if (!strncmp (path, X_("/cue/send/enable/"), 17) && strlen (path) > 17) {
6110                 if (argc == 1) {
6111                         int id = atoi (&path[17]);
6112                         ret = cue_send_enable (id, value, msg);
6113                 }
6114         }
6115         else if (!strncmp (path, X_("/cue/fader"), 10)) {
6116                 if (argc == 1) {
6117                         ret = cue_aux_fader (value, msg);
6118                 }
6119         }
6120         else if (!strncmp (path, X_("/cue/mute"), 9)) {
6121                 if (argc == 1) {
6122                         ret = cue_aux_mute (value, msg);
6123                 }
6124         }
6125
6126         return ret;
6127 }
6128
6129 int
6130 OSC::cue_set (uint32_t aux, lo_message msg)
6131 {
6132
6133         return _cue_set (aux, get_address (msg));
6134 }
6135
6136 int
6137 OSC::_cue_set (uint32_t aux, lo_address addr)
6138 {
6139         int ret = 1;
6140         OSCSurface *s = get_surface(addr, true);
6141         s->bank_size = 0;
6142         s->strip_types = 128;
6143         s->feedback = 0;
6144         s->gainmode = 1;
6145         s->cue = true;
6146         s->strips = get_sorted_stripables(s->strip_types, s->cue, false, s->custom_strips);
6147
6148         s->nstrips = s->strips.size();
6149
6150         if (aux < 1) {
6151                 aux = 1;
6152         } else if (aux > s->nstrips) {
6153                 aux = s->nstrips;
6154         }
6155         s->aux = aux;
6156         // get a list of Auxes
6157         for (uint32_t n = 0; n < s->nstrips; ++n) {
6158                 boost::shared_ptr<Stripable> stp = s->strips[n];
6159                 if (stp) {
6160                         text_message (string_compose (X_("/cue/name/%1"), n+1), stp->name(), addr);
6161                         if (aux == n+1) {
6162                                 // aux must be at least one
6163
6164                                 stp->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::_cue_set, this, aux, addr), this);
6165                                 // make a list of stripables with sends that go to this bus
6166                                 s->sends = cue_get_sorted_stripables(stp, aux, addr);
6167                                 if (s->cue_obs) {
6168                                         s->cue_obs->refresh_strip (stp, s->sends, true);
6169                                 } else {
6170                                         // start cue observer
6171                                         OSCCueObserver* co = new OSCCueObserver (*this, s);
6172                                         s->cue_obs = co;
6173                                 }
6174                                 ret = 0;
6175                         }
6176
6177                 }
6178         }
6179
6180         return ret;
6181 }
6182
6183 int
6184 OSC::cue_next (lo_message msg)
6185 {
6186         OSCSurface *s = get_surface(get_address (msg), true);
6187         int ret = 1;
6188
6189         if (!s->cue) {
6190                 ret = cue_set (1, msg);
6191         }
6192         if (s->aux < s->nstrips) {
6193                 ret = cue_set (s->aux + 1, msg);
6194         } else {
6195                 ret = cue_set (s->nstrips, msg);
6196         }
6197         return ret;
6198 }
6199
6200 int
6201 OSC::cue_previous (lo_message msg)
6202 {
6203         OSCSurface *s = get_surface(get_address (msg), true);
6204         int ret = 1;
6205         if (!s->cue) {
6206                 ret = cue_set (1, msg);
6207         }
6208         if (s->aux > 1) {
6209                 ret = cue_set (s->aux - 1, msg);
6210         } else {
6211                 ret = cue_set (1, msg);
6212         }
6213         return ret;
6214 }
6215
6216 boost::shared_ptr<Send>
6217 OSC::cue_get_send (uint32_t id, lo_address addr)
6218 {
6219         OSCSurface *s = get_surface(addr, true);
6220         if (id && s->aux > 0 && id <= s->sends.size()) {
6221                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s->sends[id - 1]);
6222                 boost::shared_ptr<Stripable> aux = get_strip (s->aux, addr);
6223                 if (r && aux) {
6224                         return r->internal_send_for (boost::dynamic_pointer_cast<Route> (aux));
6225                 }
6226         }
6227         return boost::shared_ptr<Send>();
6228
6229 }
6230
6231 int
6232 OSC::cue_aux_fader (float position, lo_message msg)
6233 {
6234         if (!session) return -1;
6235
6236         OSCSurface *sur = get_surface(get_address (msg), true);
6237         if (sur->cue) {
6238                 if (sur->aux) {
6239                         boost::shared_ptr<Stripable> s = get_strip (sur->aux, get_address (msg));
6240
6241                         if (s) {
6242                                 if (s->gain_control()) {
6243                                         s->gain_control()->set_value (s->gain_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
6244                                         return 0;
6245                                 }
6246                         }
6247                 }
6248         }
6249         float_message (X_("/cue/fader"), 0, get_address (msg));
6250         return -1;
6251 }
6252
6253 int
6254 OSC::cue_aux_mute (float state, lo_message msg)
6255 {
6256         if (!session) return -1;
6257
6258         OSCSurface *sur = get_surface(get_address (msg), true);
6259         if (sur->cue) {
6260                 if (sur->aux) {
6261                         boost::shared_ptr<Stripable> s = get_strip (sur->aux, get_address (msg));
6262                         if (s) {
6263                                 if (s->mute_control()) {
6264                                         s->mute_control()->set_value (state ? 1.0 : 0.0, PBD::Controllable::NoGroup);
6265                                         return 0;
6266                                 }
6267                         }
6268                 }
6269         }
6270         float_message (X_("/cue/mute"), 0, get_address (msg));
6271         return -1;
6272 }
6273
6274 int
6275 OSC::cue_send_fader (uint32_t id, float val, lo_message msg)
6276 {
6277         if (!session) {
6278                 return -1;
6279         }
6280         boost::shared_ptr<Send> s = cue_get_send (id, get_address (msg));
6281         if (s) {
6282                 if (s->gain_control()) {
6283                         s->gain_control()->set_value (s->gain_control()->interface_to_internal(val), PBD::Controllable::NoGroup);
6284                         return 0;
6285                 }
6286         }
6287         float_message (string_compose (X_("/cue/send/fader/%1"), id), 0, get_address (msg));
6288         return -1;
6289 }
6290
6291 int
6292 OSC::cue_send_enable (uint32_t id, float state, lo_message msg)
6293 {
6294         if (!session)
6295                 return -1;
6296         boost::shared_ptr<Send> s = cue_get_send (id, get_address (msg));
6297         if (s) {
6298                 if (state) {
6299                         s->activate ();
6300                 } else {
6301                         s->deactivate ();
6302                 }
6303                 return 0;
6304         }
6305         float_message (string_compose (X_("/cue/send/enable/%1"), id), 0, get_address (msg));
6306         return -1;
6307 }
6308
6309 // generic send message
6310 int
6311 OSC::float_message (string path, float val, lo_address addr)
6312 {
6313
6314         lo_message reply;
6315         reply = lo_message_new ();
6316         lo_message_add_float (reply, (float) val);
6317
6318         lo_send_message (addr, path.c_str(), reply);
6319         lo_message_free (reply);
6320
6321         return 0;
6322 }
6323
6324 int
6325 OSC::float_message_with_id (std::string path, uint32_t ssid, float value, bool in_line, lo_address addr)
6326 {
6327         lo_message msg = lo_message_new ();
6328         if (in_line) {
6329                 path = string_compose ("%1/%2", path, ssid);
6330         } else {
6331                 lo_message_add_int32 (msg, ssid);
6332         }
6333         lo_message_add_float (msg, value);
6334
6335         lo_send_message (addr, path.c_str(), msg);
6336         lo_message_free (msg);
6337         return 0;
6338 }
6339
6340 int
6341 OSC::int_message (string path, int val, lo_address addr)
6342 {
6343
6344         lo_message reply;
6345         reply = lo_message_new ();
6346         lo_message_add_int32 (reply, (float) val);
6347
6348         lo_send_message (addr, path.c_str(), reply);
6349         lo_message_free (reply);
6350
6351         return 0;
6352 }
6353
6354 int
6355 OSC::int_message_with_id (std::string path, uint32_t ssid, int value, bool in_line, lo_address addr)
6356 {
6357         lo_message msg = lo_message_new ();
6358         if (in_line) {
6359                 path = string_compose ("%1/%2", path, ssid);
6360         } else {
6361                 lo_message_add_int32 (msg, ssid);
6362         }
6363         lo_message_add_int32 (msg, value);
6364
6365         lo_send_message (addr, path.c_str(), msg);
6366         lo_message_free (msg);
6367         return 0;
6368 }
6369
6370 int
6371 OSC::text_message (string path, string val, lo_address addr)
6372 {
6373
6374         lo_message reply;
6375         reply = lo_message_new ();
6376         lo_message_add_string (reply, val.c_str());
6377
6378         lo_send_message (addr, path.c_str(), reply);
6379         lo_message_free (reply);
6380
6381         return 0;
6382 }
6383
6384 int
6385 OSC::text_message_with_id (std::string path, uint32_t ssid, std::string val, bool in_line, lo_address addr)
6386 {
6387         lo_message msg = lo_message_new ();
6388         if (in_line) {
6389                 path = string_compose ("%1/%2", path, ssid);
6390         } else {
6391                 lo_message_add_int32 (msg, ssid);
6392         }
6393
6394         lo_message_add_string (msg, val.c_str());
6395
6396         lo_send_message (addr, path.c_str(), msg);
6397         lo_message_free (msg);
6398         return 0;
6399 }
6400
6401 // we have to have a sorted list of stripables that have sends pointed at our aux
6402 // we can use the one in osc.cc to get an aux list
6403 OSC::Sorted
6404 OSC::cue_get_sorted_stripables(boost::shared_ptr<Stripable> aux, uint32_t id, lo_message msg)
6405 {
6406         Sorted sorted;
6407         // fetch all stripables
6408         StripableList stripables;
6409
6410         session->get_stripables (stripables);
6411
6412         // Look for stripables that have a send to aux
6413         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
6414
6415                 boost::shared_ptr<Stripable> s = *it;
6416                 // we only want routes
6417                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
6418                 if (r) {
6419                         r->processors_changed.connect  (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
6420                         boost::shared_ptr<Send> snd = r->internal_send_for (boost::dynamic_pointer_cast<Route> (aux));
6421                         if (snd) { // test for send to aux
6422                                 sorted.push_back (s);
6423                                 s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::cue_set, this, id, msg), this);
6424                         }
6425                 }
6426
6427
6428         }
6429         sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
6430
6431         return sorted;
6432 }
6433