OSC: change group sharing to individual commands
[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 (strcmp (path, X_("/select/group/gain")) == 0) {
2597                         if (argc == 1) {
2598                                 rg->set_gain ((bool) value);
2599                                 ret = 0;
2600                         }
2601                 }
2602                 else if (strcmp (path, X_("/select/group/relative")) == 0) {
2603                         if (argc == 1) {
2604                                 rg->set_relative ((bool) value, this);
2605                                 ret = 0;
2606                         }
2607                 }
2608                 else if (strcmp (path, X_("/select/group/mute")) == 0) {
2609                         if (argc == 1) {
2610                                 rg->set_mute ((bool) value);
2611                                 ret = 0;
2612                         }
2613                 }
2614                 else if (strcmp (path, X_("/select/group/solo")) == 0) {
2615                         if (argc == 1) {
2616                                 rg->set_solo ((bool) value);
2617                                 ret = 0;
2618                         }
2619                 }
2620                 else if (strcmp (path, X_("/select/group/recenable")) == 0) {
2621                         if (argc == 1) {
2622                                 rg->set_recenable ((bool) value);
2623                                 ret = 0;
2624                         }
2625                 }
2626                 else if (strcmp (path, X_("/select/group/select")) == 0) {
2627                         if (argc == 1) {
2628                                 rg->set_select ((bool) value);
2629                                 ret = 0;
2630                         }
2631                 }
2632                 else if (strcmp (path, X_("/select/group/active")) == 0) {
2633                         if (argc == 1) {
2634                                 rg->set_route_active ((bool) value);
2635                                 ret = 0;
2636                         }
2637                 }
2638                 else if (strcmp (path, X_("/select/group/color")) == 0) {
2639                         if (argc == 1) {
2640                                 rg->set_color ((bool) value);
2641                                 ret = 0;
2642                         }
2643                 }
2644                 else if (strcmp (path, X_("/select/group/monitoring")) == 0) {
2645                         if (argc == 1) {
2646                                 rg->set_monitoring ((bool) value);
2647                                 ret = 0;
2648                         }
2649                 }
2650         }
2651         return ret;
2652  }
2653
2654 // this gets called for anything that starts with /select/vca
2655 int
2656 OSC::parse_sel_vca (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
2657 {
2658         OSCSurface *sur = get_surface(get_address (msg));
2659         boost::shared_ptr<Stripable> s;
2660         if (sur->expand_enable) {
2661                 s = get_strip (sur->expand, get_address (msg));
2662         } else {
2663                 s = _select;
2664         }
2665         int ret = 1; /* unhandled */
2666         if (s) {
2667                 string svalue = "";
2668                 uint32_t ivalue = 1024;
2669                 if (strcmp (path, X_("/select/vca")) == 0) {
2670                         if (argc == 2) {
2671                                 if (types[0] == 's') {
2672                                         svalue = &argv[0]->s;
2673                                         if (types[1] == 'i') {
2674                                                 ivalue = argv[1]->i;
2675                                         } else if (types[1] == 'f') {
2676                                                 ivalue = (uint32_t) argv[1]->f;
2677                                         } else {
2678                                                 return 1;
2679                                         }
2680                                         boost::shared_ptr<VCA> vca = get_vca_by_name (svalue);
2681                                         if (vca) {
2682                                                 boost::shared_ptr<Slavable> slv = boost::dynamic_pointer_cast<Slavable> (s);
2683                                                 if (ivalue) {
2684                                                         slv->assign (vca);
2685                                                 } else {
2686                                                         slv->unassign (vca);
2687                                                 }
2688                                                 ret = 0;
2689                                         }
2690                                 }
2691                         } else {
2692                                 PBD::warning << "OSC: setting a vca needs both the vca name and it's state" << endmsg;
2693                         }
2694                 }
2695                 else if (!strncmp (path, X_("/select/vca/only"), 16)) {
2696                         if (argc == 1) {
2697                                 if (types[0] == 'f') {
2698                                         ivalue = (uint32_t) argv[0]->f;
2699                                 } else if (types[0] == 'i') {
2700                                         ivalue = (uint32_t) argv[0]->i;
2701                                 }
2702                         }
2703                         boost::shared_ptr<VCA> vca = boost::dynamic_pointer_cast<VCA> (s);
2704                         if (vca) {
2705                                 if ((argc == 1 && ivalue) || !argc) {
2706                                         sur->temp_strips.clear();
2707                                         StripableList stripables;
2708                                         session->get_stripables (stripables);
2709                                         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
2710                                                 boost::shared_ptr<Stripable> st = *it;
2711                                                 if (st->slaved_to (vca)) {
2712                                                         sur->temp_strips.push_back(st);
2713                                                 }
2714                                         }
2715                                         sur->temp_strips.push_back(s);
2716                                         sur->custom_mode = 7;
2717                                         set_bank (1, msg);
2718                                         ret = 0;
2719                                 } else {
2720                                         // key off is ignored
2721                                         ret = 0;
2722                                 }
2723                         } else {
2724                                 PBD::warning << "OSC: Select is not a VCA right now" << endmsg;
2725                         }
2726                 }
2727         }
2728         return ret;
2729 }
2730
2731 boost::shared_ptr<VCA>
2732 OSC::get_vca_by_name (std::string vname)
2733 {
2734         StripableList stripables;
2735         session->get_stripables (stripables);
2736         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
2737                 boost::shared_ptr<Stripable> s = *it;
2738                 boost::shared_ptr<VCA> v = boost::dynamic_pointer_cast<VCA> (s);
2739                 if (v) {
2740                         if (vname == v->name()) {
2741                                 return v;
2742                         }
2743                 }
2744         }
2745         return boost::shared_ptr<VCA>();
2746 }
2747
2748 int
2749 OSC::name_session (char *n, lo_message msg)
2750 {
2751         if (!session) {
2752                 return -1;
2753         }
2754         string new_name = n;
2755         char illegal = Session::session_name_is_legal (new_name);
2756
2757         if (illegal) {
2758                 PBD::warning  << (string_compose (_("To ensure compatibility with various systems\n"
2759                                     "session names may not contain a '%1' character"), illegal)) << endmsg;
2760                 return -1;
2761         }
2762         switch (session->rename (new_name)) {
2763                 case -1:
2764                         PBD::warning  << (_("That name is already in use by another directory/folder. Please try again.")) << endmsg;
2765                         break;
2766                 case 0:
2767                         return 0;
2768                         break;
2769                 default:
2770                         PBD::warning  << (_("Renaming this session failed.\nThings could be seriously messed up at this point")) << endmsg;
2771                         break;
2772         }
2773         return -1;
2774 }
2775
2776 uint32_t
2777 OSC::get_sid (boost::shared_ptr<ARDOUR::Stripable> strip, lo_address addr)
2778 {
2779         if (!strip) {
2780                 return 0;
2781         }
2782
2783         OSCSurface *s = get_surface(addr);
2784
2785         uint32_t b_size;
2786         if (!s->bank_size) {
2787                 // no banking
2788                 b_size = s->nstrips;
2789         } else {
2790                 b_size = s->bank_size;
2791         }
2792
2793         for (uint32_t n = s->bank; n < (min ((b_size + s->bank), s->nstrips + 1)); ++n) {
2794                 if (n <= s->strips.size()) {
2795                         if (strip == s->strips[n-1]) {
2796                                 return n - s->bank + 1;
2797                         }
2798                 }
2799         }
2800         // failsafe... should never get here.
2801         return 0;
2802 }
2803
2804 boost::shared_ptr<ARDOUR::Stripable>
2805 OSC::get_strip (uint32_t ssid, lo_address addr)
2806 {
2807         OSCSurface *s = get_surface(addr);
2808         if (ssid && ((ssid + s->bank - 2) < s->nstrips)) {
2809                 return s->strips[ssid + s->bank - 2];
2810         }
2811         // guess it is out of range
2812         return boost::shared_ptr<ARDOUR::Stripable>();
2813 }
2814
2815 // send and plugin paging commands
2816 int
2817 OSC::sel_send_pagesize (uint32_t size, lo_message msg)
2818 {
2819         OSCSurface *s = get_surface(get_address (msg));
2820         if  (size != s->send_page_size) {
2821                 s->send_page_size = size;
2822                 s->sel_obs->set_send_size(size);
2823         }
2824         return 0;
2825 }
2826
2827 int
2828 OSC::sel_send_page (int page, lo_message msg)
2829 {
2830         OSCSurface *s = get_surface(get_address (msg));
2831         uint32_t send_size = s->send_page_size;
2832         if (!send_size) {
2833                 send_size = s->nsends;
2834         }
2835         uint32_t max_page = (uint32_t)(s->nsends / send_size) + 1;
2836         s->send_page = s->send_page + page;
2837         if (s->send_page < 1) {
2838                 s->send_page = 1;
2839         } else if ((uint32_t)s->send_page > max_page) {
2840                 s->send_page = max_page;
2841         }
2842         s->sel_obs->set_send_page (s->send_page);
2843         return 0;
2844 }
2845
2846 int
2847 OSC::sel_plug_pagesize (uint32_t size, lo_message msg)
2848 {
2849         OSCSurface *s = get_surface(get_address (msg));
2850         if (size != s->plug_page_size) {
2851                 s->plug_page_size = size;
2852                 s->sel_obs->set_plugin_size(size);
2853         }
2854         return 0;
2855 }
2856
2857 int
2858 OSC::sel_plug_page (int page, lo_message msg)
2859 {
2860         if (!page) {
2861                 return 0;
2862         }
2863         int new_page = 0;
2864         OSCSurface *s = get_surface(get_address (msg));
2865         if (page > 0) {
2866                 new_page = s->plug_page + s->plug_page_size;
2867                 if ((uint32_t) new_page > s->plug_params.size ()) {
2868                         new_page = s->plug_page;
2869                 }
2870         } else {
2871                 new_page = s->plug_page - s->plug_page_size;
2872                 if (new_page < 1) {
2873                         new_page = 1;
2874                 }
2875         }
2876         if (new_page != s->plug_page) {
2877                 s->plug_page = new_page;
2878                 s->sel_obs->set_plugin_page(s->plug_page);
2879         }
2880         return 0;
2881 }
2882
2883 int
2884 OSC::sel_plugin (int delta, lo_message msg)
2885 {
2886         if (!delta) {
2887                 return 0;
2888         }
2889         OSCSurface *sur = get_surface(get_address (msg));
2890         return _sel_plugin (sur->plugin_id + delta, get_address (msg));
2891 }
2892
2893 int
2894 OSC::_sel_plugin (int id, lo_address addr)
2895 {
2896         OSCSurface *sur = get_surface(addr);
2897         boost::shared_ptr<Stripable> s = sur->select;
2898         if (s) {
2899                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
2900                 if (!r) {
2901                         return 1;
2902                 }
2903
2904                 // find out how many plugins we have
2905                 bool plugs;
2906                 int nplugs  = 0;
2907                 sur->plugins.clear();
2908                 do {
2909                         plugs = false;
2910                         if (r->nth_plugin (nplugs)) {
2911                                 if (r->nth_plugin(nplugs)->display_to_user()) {
2912 #ifdef MIXBUS
2913                                         // need to check for mixbus channel strips (and exclude them)
2914                                         boost::shared_ptr<Processor> proc = r->nth_plugin (nplugs);
2915                                         boost::shared_ptr<PluginInsert> pi;
2916                                         if ((pi = boost::dynamic_pointer_cast<PluginInsert>(proc))) {
2917
2918                                                 if (!pi->is_channelstrip()) {
2919 #endif
2920                                                         sur->plugins.push_back (nplugs);
2921                                                         nplugs++;
2922 #ifdef MIXBUS
2923                                                 }
2924                                         }
2925 #endif
2926                                 }
2927                                 plugs = true;
2928                         }
2929                 } while (plugs);
2930
2931                 // limit plugin_id to actual plugins
2932                 if (sur->plugins.size() < 1) {
2933                         sur->plugin_id = 0;
2934                         sur->plug_page = 1;
2935                         if (sur->sel_obs) {
2936                                 sur->sel_obs->set_plugin_id(-1, 1);
2937                         }
2938                         return 0;
2939                 } else if (id < 1) {
2940                         sur->plugin_id = 1;
2941                 } else if (sur->plugins.size() < (uint32_t) id) {
2942                         sur->plugin_id = sur->plugins.size();
2943                 } else {
2944                         sur->plugin_id = id;
2945                 }
2946
2947                 // we have a plugin number now get the processor
2948                 boost::shared_ptr<Processor> proc = r->nth_plugin (sur->plugins[sur->plugin_id - 1]);
2949                 boost::shared_ptr<PluginInsert> pi;
2950                 if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(proc))) {
2951                         PBD::warning << "OSC: Plugin: " << sur->plugin_id << " does not seem to be a plugin" << endmsg;                 
2952                         return 1;
2953                 }
2954                 boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
2955                 bool ok = false;
2956                 // put only input controls into a vector
2957                 sur->plug_params.clear ();
2958                 uint32_t nplug_params  = pip->parameter_count();
2959                 for ( uint32_t ppi = 0;  ppi < nplug_params; ++ppi) {
2960                         uint32_t controlid = pip->nth_parameter(ppi, ok);
2961                         if (!ok) {
2962                                 continue;
2963                         }
2964                         if (pip->parameter_is_input(controlid)) {
2965                                 sur->plug_params.push_back (ppi);
2966                         }
2967                 }
2968
2969                 sur->plug_page = 1;
2970
2971                 if (sur->sel_obs) {
2972                         sur->sel_obs->set_plugin_id(sur->plugins[sur->plugin_id - 1], sur->plug_page);
2973                 }
2974                 return 0;
2975         }
2976         return 1;
2977 }
2978
2979 void
2980 OSC::transport_sample (lo_message msg)
2981 {
2982         if (!session) {
2983                 return;
2984         }
2985         check_surface (msg);
2986         samplepos_t pos = session->transport_sample ();
2987
2988         lo_message reply = lo_message_new ();
2989         lo_message_add_int64 (reply, pos);
2990
2991         lo_send_message (get_address (msg), X_("/transport_frame"), reply);
2992
2993         lo_message_free (reply);
2994 }
2995
2996 void
2997 OSC::transport_speed (lo_message msg)
2998 {
2999         if (!session) {
3000                 return;
3001         }
3002         check_surface (msg);
3003         double ts = session->transport_speed ();
3004
3005         lo_message reply = lo_message_new ();
3006         lo_message_add_double (reply, ts);
3007
3008         lo_send_message (get_address (msg), X_("/transport_speed"), reply);
3009
3010         lo_message_free (reply);
3011 }
3012
3013 void
3014 OSC::record_enabled (lo_message msg)
3015 {
3016         if (!session) {
3017                 return;
3018         }
3019         check_surface (msg);
3020         int re = (int)session->get_record_enabled ();
3021
3022         lo_message reply = lo_message_new ();
3023         lo_message_add_int32 (reply, re);
3024
3025         lo_send_message (get_address (msg), X_("/record_enabled"), reply);
3026
3027         lo_message_free (reply);
3028 }
3029
3030 int
3031 OSC::scrub (float delta, lo_message msg)
3032 {
3033         if (!session) return -1;
3034         check_surface (msg);
3035
3036         scrub_place = session->transport_sample ();
3037
3038         float speed;
3039
3040         int64_t now = ARDOUR::get_microseconds ();
3041         int64_t diff = now - scrub_time;
3042         if (diff > 35000) {
3043                 // speed 1 (or 0 if jog wheel supports touch)
3044                 speed = delta;
3045         } else if ((diff > 20000) && (fabs(scrub_speed) == 1)) {
3046                 // add some hysteresis to stop excess speed jumps
3047                 speed = delta;
3048         } else {
3049                 speed = (int)(delta * 2);
3050         }
3051         scrub_time = now;
3052         if (scrub_speed == speed) {
3053                 // Already at that speed no change
3054                 return 0;
3055         }
3056         scrub_speed = speed;
3057
3058         if (speed > 0) {
3059                 if (speed == 1) {
3060                         session->request_transport_speed (.5);
3061                 } else {
3062                         session->request_transport_speed (9.9);
3063                 }
3064         } else if (speed < 0) {
3065                 if (speed == -1) {
3066                         session->request_transport_speed (-.5);
3067                 } else {
3068                         session->request_transport_speed (-1);
3069                 }
3070         } else {
3071                 session->request_transport_speed (0);
3072         }
3073
3074         return 0;
3075 }
3076
3077 int
3078 OSC::jog (float delta, lo_message msg)
3079 {
3080         if (!session) return -1;
3081
3082         OSCSurface *s = get_surface(get_address (msg));
3083
3084         switch(s->jogmode)
3085         {
3086                 case 0:
3087                         if (delta) {
3088                                 jump_by_seconds (delta / 5);
3089                         }
3090                         break;
3091                 case 1:
3092                         if (delta > 0) {
3093                                 access_action ("Common/nudge-playhead-forward");
3094                         } else if (delta < 0) {
3095                                 access_action ("Common/nudge-playhead-backward");
3096                         }
3097                         break;
3098                 case 2:
3099                         scrub (delta, msg);
3100                         break;
3101                 case 3:
3102                         if (delta) {
3103                                 double speed = get_transport_speed ();
3104                                 set_transport_speed (speed + (delta / 8.1));
3105                         } else {
3106                                 set_transport_speed (0);
3107                         }
3108                         break;
3109                 case 4:
3110                         if (delta > 0) {
3111                                 next_marker ();
3112                         } else if (delta < 0) {
3113                                 prev_marker ();
3114                         }
3115                         break;
3116                 case 5:
3117                         if (delta > 0) {
3118                                 access_action ("Editor/scroll-forward");
3119                         } else if (delta < 0) {
3120                                 access_action ("Editor/scroll-backward");
3121                         }
3122                         break;
3123                 case 6:
3124                         if (delta > 0) {
3125                                 set_bank (s->bank + 1, msg);
3126                         } else if (delta < 0) {
3127                                 set_bank (s->bank - 1, msg);
3128                         }
3129                         break;
3130                 case 7:
3131                         if (delta > 0) {
3132                                 bank_up (msg);
3133                         } else if (delta < 0) {
3134                                 bank_down (msg);
3135                         }
3136                         break;
3137                 default:
3138                         break;
3139
3140         }
3141         return 0;
3142
3143 }
3144
3145 int
3146 OSC::jog_mode (float mode, lo_message msg)
3147 {
3148         if (!session) return -1;
3149
3150         OSCSurface *s = get_surface(get_address (msg));
3151         if (get_transport_speed () != 1.0) {
3152                 set_transport_speed (0);
3153         }
3154         s->jogmode = (uint32_t) mode;
3155         s->global_obs->jog_mode (mode);
3156         return 0;
3157 }
3158
3159 // two structs to help with going to markers
3160 struct LocationMarker {
3161         LocationMarker (const std::string& l, samplepos_t w)
3162                 : label (l), when (w) {}
3163         std::string label;
3164         samplepos_t  when;
3165 };
3166
3167 struct LocationMarkerSort {
3168         bool operator() (const LocationMarker& a, const LocationMarker& b) {
3169                 return (a.when < b.when);
3170         }
3171 };
3172
3173 int
3174 OSC::set_marker (const char* types, lo_arg **argv, int argc, lo_message msg)
3175 {
3176         if (argc != 1) {
3177                 PBD::warning << "Wrong number of parameters, one only." << endmsg;
3178                 return -1;
3179         }
3180         const Locations::LocationList& ll (session->locations ()->list ());
3181         uint32_t marker = 0;
3182
3183         switch (types[0]) {
3184                 case 's':
3185                         {
3186                                 Location *cur_mark = 0;
3187                                 for (Locations::LocationList::const_iterator l = ll.begin(); l != ll.end(); ++l) {
3188                                         if ((*l)->is_mark ()) {
3189                                                 if (strcmp (&argv[0]->s, (*l)->name().c_str()) == 0) {
3190                                                         session->request_locate ((*l)->start (), false);
3191                                                         return 0;
3192                                                 } else if ((*l)->start () == session->transport_sample()) {
3193                                                         cur_mark = (*l);
3194                                                 }
3195                                         }
3196                                 }
3197                                 if (cur_mark) {
3198                                         cur_mark->set_name (&argv[0]->s);
3199                                         return 0;
3200                                 }
3201                                 PBD::warning << string_compose ("Marker: \"%1\" - does not exist", &argv[0]->s) << endmsg;
3202                                 return -1;
3203                         }
3204                         break;
3205                 case 'i':
3206                         marker = (uint32_t) argv[0]->i - 1;
3207                         break;
3208                 case 'f':
3209                         marker = (uint32_t) argv[0]->f - 1;
3210                         break;
3211                 default:
3212                         return -1;
3213                         break;
3214         }
3215         std::vector<LocationMarker> lm;
3216         // get Locations that are marks
3217         for (Locations::LocationList::const_iterator l = ll.begin(); l != ll.end(); ++l) {
3218                 if ((*l)->is_mark ()) {
3219                         lm.push_back (LocationMarker((*l)->name(), (*l)->start ()));
3220                 }
3221         }
3222         // sort them by position
3223         LocationMarkerSort location_marker_sort;
3224         std::sort (lm.begin(), lm.end(), location_marker_sort);
3225         // go there
3226         if (marker < lm.size()) {
3227                 session->request_locate (lm[marker].when, false);
3228                 return 0;
3229         }
3230         // we were unable to deal with things
3231         return -1;
3232 }
3233
3234 int
3235 OSC::group_list (lo_message msg)
3236 {
3237         return send_group_list (get_address (msg));
3238 }
3239
3240 int
3241 OSC::send_group_list (lo_address addr)
3242 {
3243         lo_message reply;
3244         reply = lo_message_new ();
3245
3246         lo_message_add_string (reply, X_("none"));
3247
3248         std::list<RouteGroup*> groups = session->route_groups ();
3249         for (std::list<RouteGroup *>::iterator i = groups.begin(); i != groups.end(); ++i) {
3250                 RouteGroup *rg = *i;
3251                 lo_message_add_string (reply, rg->name().c_str());
3252         }
3253         lo_send_message (addr, X_("/group/list"), reply);
3254         lo_message_free (reply);
3255         return 0;
3256 }
3257
3258 int
3259 OSC::click_level (float position)
3260 {
3261         if (!session) return -1;
3262         if (session->click_gain()->gain_control()) {
3263                 session->click_gain()->gain_control()->set_value (session->click_gain()->gain_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
3264         }
3265         return 0;
3266 }
3267
3268 // master and monitor calls
3269 int
3270 OSC::master_set_gain (float dB)
3271 {
3272         if (!session) return -1;
3273         boost::shared_ptr<Stripable> s = session->master_out();
3274         if (s) {
3275                 if (dB < -192) {
3276                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
3277                 } else {
3278                         float abs = dB_to_coefficient (dB);
3279                         float top = s->gain_control()->upper();
3280                         if (abs > top) {
3281                                 abs = top;
3282                         }
3283                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3284                 }
3285         }
3286         return 0;
3287 }
3288
3289 int
3290 OSC::master_delta_gain (float delta)
3291 {
3292         if (!session) return -1;
3293         boost::shared_ptr<Stripable> s = session->master_out();
3294         if (s) {
3295                 float dB = accurate_coefficient_to_dB (s->gain_control()->get_value()) + delta;
3296                 if (dB < -192) {
3297                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
3298                 } else {
3299                         float abs = dB_to_coefficient (dB);
3300                         float top = s->gain_control()->upper();
3301                         if (abs > top) {
3302                                 abs = top;
3303                         }
3304                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3305                 }
3306         }
3307         return 0;
3308 }
3309
3310 int
3311 OSC::master_set_fader (float position)
3312 {
3313         if (!session) return -1;
3314         boost::shared_ptr<Stripable> s = session->master_out();
3315         if (s) {
3316                 s->gain_control()->set_value (s->gain_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
3317         }
3318         return 0;
3319 }
3320
3321 int
3322 OSC::master_set_trim (float dB)
3323 {
3324         if (!session) return -1;
3325         boost::shared_ptr<Stripable> s = session->master_out();
3326
3327         if (s) {
3328                 s->trim_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
3329         }
3330
3331         return 0;
3332 }
3333
3334 int
3335 OSC::master_set_pan_stereo_position (float position, lo_message msg)
3336 {
3337         if (!session) return -1;
3338         OSCSurface *sur = get_surface(get_address (msg));
3339
3340         float endposition = .5;
3341         boost::shared_ptr<Stripable> s = session->master_out();
3342
3343         if (s) {
3344                 if (s->pan_azimuth_control()) {
3345                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
3346                         endposition = s->pan_azimuth_control()->internal_to_interface (s->pan_azimuth_control()->get_value ());
3347                 }
3348         }
3349
3350         if (sur->feedback[4]) {
3351                 lo_message reply = lo_message_new ();
3352                 lo_message_add_float (reply, endposition);
3353
3354                 lo_send_message (get_address (msg), X_("/master/pan_stereo_position"), reply);
3355                 lo_message_free (reply);
3356         }
3357
3358         return 0;
3359 }
3360
3361 int
3362 OSC::master_set_mute (uint32_t state)
3363 {
3364         if (!session) return -1;
3365
3366         boost::shared_ptr<Stripable> s = session->master_out();
3367
3368         if (s) {
3369                 s->mute_control()->set_value (state, PBD::Controllable::NoGroup);
3370         }
3371
3372         return 0;
3373 }
3374
3375 int
3376 OSC::master_select (lo_message msg)
3377 {
3378         if (!session) {
3379                 return -1;
3380         }
3381         OSCSurface *sur = get_surface(get_address (msg));
3382         sur->expand_enable = false;
3383         boost::shared_ptr<Stripable> s = session->master_out();
3384         if (s) {
3385                 SetStripableSelection (s);
3386         }
3387
3388         return 0;
3389 }
3390
3391 int
3392 OSC::monitor_set_gain (float dB)
3393 {
3394         if (!session) return -1;
3395         boost::shared_ptr<Stripable> s = session->monitor_out();
3396
3397         if (s) {
3398                 if (dB < -192) {
3399                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
3400                 } else {
3401                         float abs = dB_to_coefficient (dB);
3402                         float top = s->gain_control()->upper();
3403                         if (abs > top) {
3404                                 abs = top;
3405                         }
3406                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3407                 }
3408         }
3409         return 0;
3410 }
3411
3412 int
3413 OSC::monitor_delta_gain (float delta)
3414 {
3415         if (!session) return -1;
3416         boost::shared_ptr<Stripable> s = session->monitor_out();
3417         if (s) {
3418                 float dB = accurate_coefficient_to_dB (s->gain_control()->get_value()) + delta;
3419                 if (dB < -192) {
3420                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
3421                 } else {
3422                         float abs = dB_to_coefficient (dB);
3423                         float top = s->gain_control()->upper();
3424                         if (abs > top) {
3425                                 abs = top;
3426                         }
3427                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3428                 }
3429         }
3430         return 0;
3431 }
3432
3433 int
3434 OSC::monitor_set_fader (float position)
3435 {
3436         if (!session) return -1;
3437         boost::shared_ptr<Stripable> s = session->monitor_out();
3438         if (s) {
3439                 s->gain_control()->set_value (s->gain_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
3440         }
3441         return 0;
3442 }
3443
3444 int
3445 OSC::monitor_set_mute (uint32_t state)
3446 {
3447         if (!session) return -1;
3448
3449         if (session->monitor_out()) {
3450                 boost::shared_ptr<MonitorProcessor> mon = session->monitor_out()->monitor_control();
3451                 mon->set_cut_all (state);
3452         }
3453         return 0;
3454 }
3455
3456 int
3457 OSC::monitor_set_dim (uint32_t state)
3458 {
3459         if (!session) return -1;
3460
3461         if (session->monitor_out()) {
3462                 boost::shared_ptr<MonitorProcessor> mon = session->monitor_out()->monitor_control();
3463                 mon->set_dim_all (state);
3464         }
3465         return 0;
3466 }
3467
3468 int
3469 OSC::monitor_set_mono (uint32_t state)
3470 {
3471         if (!session) return -1;
3472
3473         if (session->monitor_out()) {
3474                 boost::shared_ptr<MonitorProcessor> mon = session->monitor_out()->monitor_control();
3475                 mon->set_mono (state);
3476         }
3477         return 0;
3478 }
3479
3480 int
3481 OSC::route_get_sends(lo_message msg) {
3482         if (!session) {
3483                 return -1;
3484         }
3485
3486         lo_arg **argv = lo_message_get_argv(msg);
3487
3488         int rid = argv[0]->i;
3489
3490         boost::shared_ptr<Stripable> strip = get_strip(rid, get_address(msg));
3491         if (!strip) {
3492                 return -1;
3493         }
3494
3495         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (strip);
3496         if (!r) {
3497                 return -1;
3498         }
3499
3500         lo_message reply = lo_message_new();
3501         lo_message_add_int32(reply, rid);
3502
3503         int i = 0;
3504         for (;;) {
3505                 boost::shared_ptr<Processor> p = r->nth_send(i++);
3506
3507                 if (!p) {
3508                         break;
3509                 }
3510
3511                 boost::shared_ptr<InternalSend> isend = boost::dynamic_pointer_cast<InternalSend> (p);
3512                 if (isend) {
3513                         lo_message_add_int32(reply, get_sid(isend->target_route(), get_address(msg)));
3514                         lo_message_add_string(reply, isend->name().c_str());
3515                         lo_message_add_int32(reply, i);
3516                         boost::shared_ptr<Amp> a = isend->amp();
3517                         lo_message_add_float(reply, a->gain_control()->internal_to_interface (a->gain_control()->get_value()));
3518                         lo_message_add_int32(reply, p->active() ? 1 : 0);
3519                 }
3520         }
3521         // if used dedicated message path to identify this reply in async operation.
3522         // Naming it #reply wont help the client to identify the content.
3523         lo_send_message(get_address (msg), X_("/strip/sends"), reply);
3524
3525         lo_message_free(reply);
3526
3527         return 0;
3528 }
3529
3530 int
3531 OSC::route_get_receives(lo_message msg) {
3532         if (!session) {
3533                 return -1;
3534         }
3535
3536         lo_arg **argv = lo_message_get_argv(msg);
3537
3538         uint32_t rid = argv[0]->i;
3539
3540
3541         boost::shared_ptr<Stripable> strip = get_strip(rid, get_address(msg));
3542         if (!strip) {
3543                 return -1;
3544         }
3545
3546         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (strip);
3547         if (!r) {
3548                 return -1;
3549         }
3550
3551         boost::shared_ptr<RouteList> route_list = session->get_routes();
3552
3553         lo_message reply = lo_message_new();
3554         lo_message_add_int32(reply, rid);
3555
3556         for (RouteList::iterator i = route_list->begin(); i != route_list->end(); ++i) {
3557                 boost::shared_ptr<Route> tr = boost::dynamic_pointer_cast<Route> (*i);
3558                 if (!tr) {
3559                         continue;
3560                 }
3561                 int j = 0;
3562
3563                 for (;;) {
3564                         boost::shared_ptr<Processor> p = tr->nth_send(j++);
3565
3566                         if (!p) {
3567                                 break;
3568                         }
3569
3570                         boost::shared_ptr<InternalSend> isend = boost::dynamic_pointer_cast<InternalSend> (p);
3571                         if (isend) {
3572                                 if( isend->target_route()->id() == r->id()){
3573                                         boost::shared_ptr<Amp> a = isend->amp();
3574
3575                                         lo_message_add_int32(reply, get_sid(tr, get_address(msg)));
3576                                         lo_message_add_string(reply, tr->name().c_str());
3577                                         lo_message_add_int32(reply, j);
3578                                         lo_message_add_float(reply, a->gain_control()->internal_to_interface (a->gain_control()->get_value()));
3579                                         lo_message_add_int32(reply, p->active() ? 1 : 0);
3580                                 }
3581                         }
3582                 }
3583         }
3584
3585         // I have used a dedicated message path to identify this reply in async operation.
3586         // Naming it #reply wont help the client to identify the content.
3587         lo_send_message(get_address (msg), X_("/strip/receives"), reply);
3588         lo_message_free(reply);
3589         return 0;
3590 }
3591
3592 // strip calls
3593
3594 int
3595 OSC::set_automation (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
3596 {
3597         if (!session) return -1;
3598
3599         int ret = 1;
3600         OSCSurface *sur = get_surface(get_address (msg));
3601         boost::shared_ptr<Stripable> strp = boost::shared_ptr<Stripable>();
3602         uint32_t ctr = 0;
3603         uint32_t aut = 0;
3604         uint32_t ssid;
3605
3606         if (argc) {
3607                 if (types[argc - 1] == 'f') {
3608                         aut = (int)argv[argc - 1]->f;
3609                 } else {
3610                         aut = argv[argc - 1]->i;
3611                 }
3612         }
3613
3614         //parse path first to find stripable
3615         if (!strncmp (path, X_("/strip/"), 7)) {
3616                 // find ssid and stripable
3617                 if (argc > 1) {
3618                         if (types[1] == 'f') {
3619                                 ssid = (uint32_t)argv[0]->f;
3620                         } else {
3621                                 ssid = argv[0]->i;
3622                         }
3623                         strp = get_strip (ssid, get_address (msg));
3624                 } else {
3625                         ssid = atoi (&(strrchr (path, '/' ))[1]);
3626                         strp = get_strip (ssid, get_address (msg));
3627                 }
3628                 ctr = 7;
3629         } else if (!strncmp (path, X_("/select/"), 8)) {
3630                 if (sur->expand_enable && sur->expand) {
3631                         strp = get_strip (sur->expand, get_address (msg));
3632                 } else {
3633                         strp = _select;
3634                 }
3635                 ctr = 8;
3636         } else {
3637                 return ret;
3638         }
3639         if (strp) {
3640                 boost::shared_ptr<AutomationControl> control = boost::shared_ptr<AutomationControl>();
3641                 // other automatable controls can be added by repeating the next 6.5 lines
3642                 if ((!strncmp (&path[ctr], X_("fader"), 5)) || (!strncmp (&path[ctr], X_("gain"), 4))) {
3643                         if (strp->gain_control ()) {
3644                                 control = strp->gain_control ();
3645                         } else {
3646                                 PBD::warning << "No fader for this strip" << endmsg;
3647                         }
3648                 } else {
3649                         PBD::warning << "Automation not available for " << path << endmsg;
3650                 }
3651
3652                 if (control) {
3653
3654                         switch (aut) {
3655                                 case 0:
3656                                         control->set_automation_state (ARDOUR::Off);
3657                                         ret = 0;
3658                                         break;
3659                                 case 1:
3660                                         control->set_automation_state (ARDOUR::Play);
3661                                         ret = 0;
3662                                         break;
3663                                 case 2:
3664                                         control->set_automation_state (ARDOUR::Write);
3665                                         ret = 0;
3666                                         break;
3667                                 case 3:
3668                                         control->set_automation_state (ARDOUR::Touch);
3669                                         ret = 0;
3670                                         break;
3671                                 default:
3672                                         break;
3673                         }
3674                 }
3675         }
3676
3677         return ret;
3678 }
3679
3680 int
3681 OSC::touch_detect (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
3682 {
3683         if (!session) return -1;
3684
3685         int ret = 1;
3686         OSCSurface *sur = get_surface(get_address (msg));
3687         boost::shared_ptr<Stripable> strp = boost::shared_ptr<Stripable>();
3688         uint32_t ctr = 0;
3689         uint32_t touch = 0;
3690         uint32_t ssid;
3691
3692         if (argc) {
3693                 if (types[argc - 1] == 'f') {
3694                         touch = (int)argv[argc - 1]->f;
3695                 } else {
3696                         touch = argv[argc - 1]->i;
3697                 }
3698         }
3699
3700         //parse path first to find stripable
3701         if (!strncmp (path, X_("/strip/"), 7)) {
3702                 // find ssid and stripable
3703                 if (argc > 1) {
3704                         if (types[0] == 'f') {
3705                                 ssid = (uint32_t)argv[0]->f;
3706                         } else {
3707                                 ssid = argv[0]->i;
3708                         }
3709                         strp = get_strip (ssid, get_address (msg));
3710                 } else {
3711                         ssid = atoi (&(strrchr (path, '/' ))[1]);
3712                         strp = get_strip (ssid, get_address (msg));
3713                 }
3714                 ctr = 7;
3715         } else if (!strncmp (path, X_("/select/"), 8)) {
3716                 if (sur->expand_enable && sur->expand) {
3717                         strp = get_strip (sur->expand, get_address (msg));
3718                 } else {
3719                         strp = _select;
3720                 }
3721                 ctr = 8;
3722         } else {
3723                 return ret;
3724         }
3725         if (strp) {
3726                 boost::shared_ptr<AutomationControl> control = boost::shared_ptr<AutomationControl>();
3727                 // other automatable controls can be added by repeating the next 6.5 lines
3728                 if ((!strncmp (&path[ctr], X_("fader"), 5)) || (!strncmp (&path[ctr], X_("gain"), 4))) {
3729                         if (strp->gain_control ()) {
3730                                 control = strp->gain_control ();
3731                         } else {
3732                                 PBD::warning << "No fader for this strip" << endmsg;
3733                         }
3734                 } else {
3735                         PBD::warning << "Automation not available for " << path << endmsg;
3736                 }
3737
3738                 if (control) {
3739                         if (touch) {
3740                                 //start touch
3741                                 control->start_touch (control->session().transport_sample());
3742                                 ret = 0;
3743                         } else {
3744                                 // end touch
3745                                 control->stop_touch (control->session().transport_sample());
3746                                 ret = 0;
3747                         }
3748                         // just in case some crazy surface starts sending control values before touch
3749                         FakeTouchMap::iterator x = _touch_timeout.find(control);
3750                         if (x != _touch_timeout.end()) {
3751                                 _touch_timeout.erase (x);
3752                         }
3753                 }
3754         }
3755
3756         return ret;
3757 }
3758
3759 int
3760 OSC::fake_touch (boost::shared_ptr<ARDOUR::AutomationControl> ctrl)
3761 {
3762         if (ctrl) {
3763                 //start touch
3764                 if (ctrl->automation_state() == Touch && !ctrl->touching ()) {
3765                 ctrl->start_touch (ctrl->session().transport_sample());
3766                 _touch_timeout[ctrl] = 10;
3767                 }
3768         }
3769
3770         return 0;
3771 }
3772
3773 int
3774 OSC::route_mute (int ssid, int yn, lo_message msg)
3775 {
3776         if (!session) return -1;
3777         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3778         OSCSurface *sur = get_surface(get_address (msg));
3779
3780         if (s) {
3781                 if (s->mute_control()) {
3782                         s->mute_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
3783                         return 0;
3784                 }
3785         }
3786
3787         return float_message_with_id (X_("/strip/mute"), ssid, 0, sur->feedback[2], get_address (msg));
3788 }
3789
3790 int
3791 OSC::sel_mute (uint32_t yn, lo_message msg)
3792 {
3793         OSCSurface *sur = get_surface(get_address (msg));
3794         boost::shared_ptr<Stripable> s;
3795         if (sur->expand_enable) {
3796                 s = get_strip (sur->expand, get_address (msg));
3797         } else {
3798                 s = _select;
3799         }
3800         if (s) {
3801                 if (s->mute_control()) {
3802                         s->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3803                         return 0;
3804                 }
3805         }
3806         return float_message(X_("/select/mute"), 0, get_address (msg));
3807 }
3808
3809 int
3810 OSC::route_solo (int ssid, int yn, lo_message msg)
3811 {
3812         if (!session) return -1;
3813         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3814         OSCSurface *sur = get_surface(get_address (msg));
3815
3816         if (s) {
3817                 if (s->solo_control()) {
3818                         s->solo_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
3819                 }
3820         }
3821
3822         return float_message_with_id (X_("/strip/solo"), ssid, 0, sur->feedback[2], get_address (msg));
3823 }
3824
3825 int
3826 OSC::route_solo_iso (int ssid, int yn, lo_message msg)
3827 {
3828         if (!session) return -1;
3829         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3830         OSCSurface *sur = get_surface(get_address (msg));
3831
3832         if (s) {
3833                 if (s->solo_isolate_control()) {
3834                         s->solo_isolate_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
3835                         return 0;
3836                 }
3837         }
3838
3839         return float_message_with_id (X_("/strip/solo_iso"), ssid, 0, sur->feedback[2], get_address (msg));
3840 }
3841
3842 int
3843 OSC::route_solo_safe (int ssid, int yn, lo_message msg)
3844 {
3845         if (!session) return -1;
3846         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
3847         OSCSurface *sur = get_surface(get_address (msg));
3848
3849         if (s) {
3850                 if (s->solo_safe_control()) {
3851                         s->solo_safe_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
3852                         return 0;
3853                 }
3854         }
3855
3856         return float_message_with_id (X_("/strip/solo_safe"), ssid, 0, sur->feedback[2], get_address (msg));
3857 }
3858
3859 int
3860 OSC::sel_solo (uint32_t yn, lo_message msg)
3861 {
3862         OSCSurface *sur = get_surface(get_address (msg));
3863         boost::shared_ptr<Stripable> s;
3864         if (sur->expand_enable) {
3865                 s = get_strip (sur->expand, get_address (msg));
3866         } else {
3867                 s = _select;
3868         }
3869         if (s) {
3870                 if (s->solo_control()) {
3871                         session->set_control (s->solo_control(), yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3872                 }
3873         }
3874         return float_message(X_("/select/solo"), 0, get_address (msg));
3875 }
3876
3877 int
3878 OSC::sel_solo_iso (uint32_t yn, lo_message msg)
3879 {
3880         OSCSurface *sur = get_surface(get_address (msg));
3881         boost::shared_ptr<Stripable> s;
3882         if (sur->expand_enable) {
3883                 s = get_strip (sur->expand, get_address (msg));
3884         } else {
3885                 s = _select;
3886         }
3887         if (s) {
3888                 if (s->solo_isolate_control()) {
3889                         s->solo_isolate_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3890                         return 0;
3891                 }
3892         }
3893         return float_message(X_("/select/solo_iso"), 0, get_address (msg));
3894 }
3895
3896 int
3897 OSC::sel_solo_safe (uint32_t yn, lo_message msg)
3898 {
3899         OSCSurface *sur = get_surface(get_address (msg));
3900         boost::shared_ptr<Stripable> s;
3901         if (sur->expand_enable) {
3902                 s = get_strip (sur->expand, get_address (msg));
3903         } else {
3904                 s = _select;
3905         }
3906         if (s) {
3907                 if (s->solo_safe_control()) {
3908                         s->solo_safe_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3909                         return 0;
3910                 }
3911         }
3912         return float_message(X_("/select/solo_safe"), 0, get_address (msg));
3913 }
3914
3915 int
3916 OSC::sel_recenable (uint32_t yn, lo_message msg)
3917 {
3918         OSCSurface *sur = get_surface(get_address (msg));
3919         boost::shared_ptr<Stripable> s;
3920         if (sur->expand_enable) {
3921                 s = get_strip (sur->expand, get_address (msg));
3922         } else {
3923                 s = _select;
3924         }
3925         if (s) {
3926                 if (s->rec_enable_control()) {
3927                         s->rec_enable_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3928                         if (s->rec_enable_control()->get_value()) {
3929                                 return 0;
3930                         }
3931                 }
3932         }
3933         return float_message(X_("/select/recenable"), 0, get_address (msg));
3934 }
3935
3936 int
3937 OSC::route_recenable (int ssid, int yn, lo_message msg)
3938 {
3939         if (!session) return -1;
3940         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3941         OSCSurface *sur = get_surface(get_address (msg));
3942
3943         if (s) {
3944                 if (s->rec_enable_control()) {
3945                         s->rec_enable_control()->set_value (yn, sur->usegroup);
3946                         if (s->rec_enable_control()->get_value()) {
3947                                 return 0;
3948                         }
3949                 }
3950         }
3951         return float_message_with_id (X_("/strip/recenable"), ssid, 0, sur->feedback[2], get_address (msg));
3952 }
3953
3954 int
3955 OSC::route_rename (int ssid, char *newname, lo_message msg) {
3956         if (!session) {
3957                 return -1;
3958         }
3959
3960         boost::shared_ptr<Stripable> s = get_strip(ssid, get_address(msg));
3961
3962         if (s) {
3963                 s->set_name(std::string(newname));
3964         }
3965
3966         return 0;
3967 }
3968
3969 int
3970 OSC::sel_rename (char *newname, 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                 s->set_name(std::string(newname));
3984         }
3985
3986         return 0;
3987 }
3988
3989 int
3990 OSC::sel_comment (char *newcomment, lo_message msg) {
3991         if (!session) {
3992                 return -1;
3993         }
3994
3995         OSCSurface *sur = get_surface(get_address (msg));
3996         boost::shared_ptr<Stripable> s;
3997         if (sur->expand_enable) {
3998                 s = get_strip (sur->expand, get_address (msg));
3999         } else {
4000                 s = _select;
4001         }
4002         if (s) {
4003                 boost::shared_ptr<Route> rt = boost::dynamic_pointer_cast<Route> (s);
4004                 if (!rt) {
4005                         PBD::warning << "OSC: can not set comment on VCAs." << endmsg;
4006                         return -1;
4007                 }
4008                 rt->set_comment (newcomment, this);
4009         }
4010
4011         return 0;
4012 }
4013
4014 int
4015 OSC::strip_group (int ssid, char *group, lo_message msg) {
4016         if (!session) {
4017                 return -1;
4018         }
4019         boost::shared_ptr<Stripable> s = get_strip(ssid, get_address(msg));
4020         return strip_select_group (s, group);
4021 }
4022
4023 int
4024 OSC::sel_group (char *group, lo_message msg) {
4025         if (!session) {
4026                 return -1;
4027         }
4028         OSCSurface *sur = get_surface(get_address (msg));
4029         boost::shared_ptr<Stripable> s;
4030         if (sur->expand_enable) {
4031                 s = get_strip (sur->expand, get_address (msg));
4032         } else {
4033                 s = _select;
4034         }
4035         return strip_select_group (s, group);
4036 }
4037
4038 int
4039 OSC::strip_select_group (boost::shared_ptr<Stripable> s, char *group)
4040 {
4041         string grp = group;
4042         if (grp == "" || grp == " ") {
4043                         grp = "none";
4044                 }
4045
4046         if (s) {
4047                 boost::shared_ptr<Route> rt = boost::dynamic_pointer_cast<Route> (s);
4048                 if (!rt) {
4049                         PBD::warning << "OSC: VCAs can not be part of a group." << endmsg;
4050                         return -1;
4051                 }
4052                 RouteGroup *rg = rt->route_group();
4053                 RouteGroup* new_rg = session->route_group_by_name (grp);
4054                 if (rg) {
4055                         string old_group = rg->name();
4056                         if (grp == "none") {
4057                                 if (rg->size () == 1) {
4058                                         session->remove_route_group (*rg);
4059                                 } else {
4060                                         rg->remove (rt);
4061                                 }
4062                         } else if (grp != old_group) {
4063                                 if (new_rg) {
4064                                         // group exists switch to it
4065                                         if (rg->size () == 1) {
4066                                                 session->remove_route_group (rg);
4067                                         } else {
4068                                                 rg->remove (rt);
4069                                         }
4070                                         new_rg->add (rt);
4071                                 } else {
4072                                         rg->set_name (grp);
4073                                 }
4074                         } else {
4075                                 return 0;
4076                         }
4077                 } else {
4078                         if (grp == "none") {
4079                                 return 0;
4080                         } else if (new_rg) {
4081                                 new_rg->add (rt);
4082                         } else {
4083                                 // create new group with this strip in it
4084                                 RouteGroup* new_rg = new RouteGroup (*session, grp);
4085                                 session->add_route_group (new_rg);
4086                                 new_rg->add (rt);
4087                         }
4088                 }
4089         }
4090         return 0;
4091 }
4092
4093 int
4094 OSC::sel_recsafe (uint32_t yn, lo_message msg)
4095 {
4096         OSCSurface *sur = get_surface(get_address (msg));
4097         boost::shared_ptr<Stripable> s;
4098         if (sur->expand_enable) {
4099                 s = get_strip (sur->expand, get_address (msg));
4100         } else {
4101                 s = _select;
4102         }
4103         if (s) {
4104                 if (s->rec_safe_control()) {
4105                         s->rec_safe_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
4106                         if (s->rec_safe_control()->get_value()) {
4107                                 return 0;
4108                         }
4109                 }
4110         }
4111         return float_message(X_("/select/record_safe"), 0, get_address (msg));
4112 }
4113
4114 int
4115 OSC::route_recsafe (int ssid, int yn, lo_message msg)
4116 {
4117         if (!session) return -1;
4118         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4119         OSCSurface *sur = get_surface(get_address (msg));
4120         if (s) {
4121                 if (s->rec_safe_control()) {
4122                         s->rec_safe_control()->set_value (yn, sur->usegroup);
4123                         if (s->rec_safe_control()->get_value()) {
4124                                 return 0;
4125                         }
4126                 }
4127         }
4128         return float_message_with_id (X_("/strip/record_safe"), ssid, 0, sur->feedback[2], get_address (msg));
4129 }
4130
4131 int
4132 OSC::route_monitor_input (int ssid, int yn, lo_message msg)
4133 {
4134         if (!session) return -1;
4135         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4136         OSCSurface *sur = get_surface(get_address (msg));
4137
4138         if (s) {
4139                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
4140                 if (track) {
4141                         if (track->monitoring_control()) {
4142                                 std::bitset<32> value = track->monitoring_control()->get_value ();
4143                                 value[0] = yn ? 1 : 0;
4144                                 track->monitoring_control()->set_value (value.to_ulong(), sur->usegroup);
4145                                 return 0;
4146                         }
4147                 }
4148         }
4149
4150         return float_message_with_id (X_("/strip/monitor_input"), ssid, 0, sur->feedback[2], get_address (msg));
4151 }
4152
4153 int
4154 OSC::sel_monitor_input (uint32_t yn, lo_message msg)
4155 {
4156         OSCSurface *sur = get_surface(get_address (msg));
4157         boost::shared_ptr<Stripable> s;
4158         if (sur->expand_enable) {
4159                 s = get_strip (sur->expand, get_address (msg));
4160         } else {
4161                 s = _select;
4162         }
4163         if (s) {
4164                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
4165                 if (track) {
4166                         if (track->monitoring_control()) {
4167                                 std::bitset<32> value = track->monitoring_control()->get_value ();
4168                                 value[0] = yn ? 1 : 0;
4169                                 track->monitoring_control()->set_value (value.to_ulong(), sur->usegroup);
4170                                 return 0;
4171                         }
4172                 }
4173         }
4174         return float_message(X_("/select/monitor_input"), 0, get_address (msg));
4175 }
4176
4177 int
4178 OSC::route_monitor_disk (int ssid, int yn, lo_message msg)
4179 {
4180         if (!session) return -1;
4181         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4182         OSCSurface *sur = get_surface(get_address (msg));
4183
4184         if (s) {
4185                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
4186                 if (track) {
4187                         if (track->monitoring_control()) {
4188                                 std::bitset<32> value = track->monitoring_control()->get_value ();
4189                                 value[1] = yn ? 1 : 0;
4190                                 track->monitoring_control()->set_value (value.to_ulong(), sur->usegroup);
4191                                 return 0;
4192                         }
4193                 }
4194         }
4195
4196         return float_message_with_id (X_("/strip/monitor_disk"), ssid, 0, sur->feedback[2], get_address (msg));
4197 }
4198
4199 int
4200 OSC::sel_monitor_disk (uint32_t yn, lo_message msg)
4201 {
4202         OSCSurface *sur = get_surface(get_address (msg));
4203         boost::shared_ptr<Stripable> s;
4204         if (sur->expand_enable) {
4205                 s = get_strip (sur->expand, get_address (msg));
4206         } else {
4207                 s = _select;
4208         }
4209         if (s) {
4210                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
4211                 if (track) {
4212                         if (track->monitoring_control()) {
4213                                 std::bitset<32> value = track->monitoring_control()->get_value ();
4214                                 value[1] = yn ? 1 : 0;
4215                                 track->monitoring_control()->set_value (value.to_ulong(), sur->usegroup);
4216                                 return 0;
4217                         }
4218                 }
4219         }
4220         return float_message(X_("/select/monitor_disk"), 0, get_address (msg));
4221 }
4222
4223
4224 int
4225 OSC::strip_phase (int ssid, int yn, lo_message msg)
4226 {
4227         if (!session) return -1;
4228         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4229         OSCSurface *sur = get_surface(get_address (msg));
4230
4231         if (s) {
4232                 if (s->phase_control()) {
4233                         s->phase_control()->set_value (yn ? 1.0 : 0.0, sur->usegroup);
4234                         return 0;
4235                 }
4236         }
4237
4238         return float_message_with_id (X_("/strip/polarity"), ssid, 0, sur->feedback[2], get_address (msg));
4239 }
4240
4241 int
4242 OSC::sel_phase (uint32_t yn, lo_message msg)
4243 {
4244         OSCSurface *sur = get_surface(get_address (msg));
4245         boost::shared_ptr<Stripable> s;
4246         if (sur->expand_enable) {
4247                 s = get_strip (sur->expand, get_address (msg));
4248         } else {
4249                 s = _select;
4250         }
4251         if (s) {
4252                 if (s->phase_control()) {
4253                         s->phase_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
4254                         return 0;
4255                 }
4256         }
4257         return float_message(X_("/select/polarity"), 0, get_address (msg));
4258 }
4259
4260 int
4261 OSC::strip_expand (int ssid, int yn, lo_message msg)
4262 {
4263         OSCSurface *sur = get_surface(get_address (msg));
4264         sur->expand_enable = (bool) yn;
4265         sur->expand = ssid;
4266         boost::shared_ptr<Stripable> s;
4267         if (yn) {
4268                 s = get_strip (ssid, get_address (msg));
4269         } else {
4270                 s = _select;
4271         }
4272
4273         return _strip_select (s, get_address (msg));
4274 }
4275
4276 int
4277 OSC::strip_hide (int ssid, int state, lo_message msg)
4278 {
4279         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4280
4281         if (s) {
4282                 if (state != s->is_hidden ()) {
4283                         s->presentation_info().set_hidden ((bool) state);
4284                 }
4285         }
4286         return 0;
4287 }
4288
4289 int
4290 OSC::_strip_select (boost::shared_ptr<Stripable> s, lo_address addr)
4291 {
4292         if (!session) {
4293                 return -1;
4294         }
4295         OSCSurface *sur = get_surface(addr, true);
4296         if (!s) {
4297                 // expand doesn't point to a stripable, turn it off and use select
4298                 sur->expand = 0;
4299                 sur->expand_enable = false;
4300                 if (ControlProtocol::first_selected_stripable()) {
4301                         s = ControlProtocol::first_selected_stripable();
4302                 } else {
4303                         s = session->master_out ();
4304                 }
4305                         _select = s;
4306         }
4307         sur->select = s;
4308         bool sends;
4309         uint32_t nsends  = 0;
4310         do {
4311                 sends = false;
4312                 if (s->send_level_controllable (nsends)) {
4313                         sends = true;
4314                         nsends++;
4315                 }
4316         } while (sends);
4317         sur->nsends = nsends;
4318
4319         s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
4320
4321         OSCSelectObserver* so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs);
4322         if (sur->feedback[13]) {
4323                 if (so != 0) {
4324                         so->refresh_strip (s, nsends, sur->gainmode, true);
4325                 } else {
4326                         OSCSelectObserver* sel_fb = new OSCSelectObserver (*this, *session, sur);
4327                         sur->sel_obs = sel_fb;
4328                 }
4329                 sur->sel_obs->set_expand (sur->expand_enable);
4330                 uint32_t obs_expand = 0;
4331                 if (sur->expand_enable) {
4332                         obs_expand = sur->expand;
4333                 } else {
4334                         obs_expand = 0;
4335                 }
4336                 for (uint32_t i = 0; i < sur->observers.size(); i++) {
4337                         sur->observers[i]->set_expand (obs_expand);
4338                 }
4339         } else {
4340                 if (so != 0) {
4341                         delete so;
4342                         sur->sel_obs = 0;
4343                 }
4344         }
4345         // need to set monitor for processor changed signal (for paging)
4346         string address = lo_address_get_url (addr);
4347         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
4348         if (r) {
4349                 r->processors_changed.connect  (sur->proc_connection, MISSING_INVALIDATOR, boost::bind (&OSC::processor_changed, this, address), this);
4350                 _sel_plugin (sur->plugin_id, addr);
4351         }
4352
4353         return 0;
4354 }
4355
4356 void
4357 OSC::processor_changed (string address)
4358 {
4359         lo_address addr = lo_address_new_from_url (address.c_str());
4360         OSCSurface *sur = get_surface (addr);
4361         _sel_plugin (sur->plugin_id, addr);
4362         if (sur->sel_obs) {
4363                 sur->sel_obs->renew_sends ();
4364                 sur->sel_obs->eq_restart (-1);
4365         }
4366 }
4367
4368 int
4369 OSC::strip_gui_select (int ssid, int yn, lo_message msg)
4370 {
4371         //ignore button release
4372         if (!yn) return 0;
4373
4374         if (!session) {
4375                 return -1;
4376         }
4377         OSCSurface *sur = get_surface(get_address (msg));
4378         sur->expand_enable = false;
4379         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4380         if (s) {
4381                 SetStripableSelection (s);
4382         } else {
4383                 if ((int) (sur->feedback.to_ulong())) {
4384                         float_message_with_id (X_("/strip/select"), ssid, 0, sur->feedback[2], get_address (msg));
4385                 }
4386         }
4387
4388         return 0;
4389 }
4390
4391 int
4392 OSC::sel_expand (uint32_t state, lo_message msg)
4393 {
4394         OSCSurface *sur = get_surface(get_address (msg));
4395         boost::shared_ptr<Stripable> s;
4396         if (state && sur->expand) {
4397                 sur->expand_enable = (bool) state;
4398                 s = get_strip (sur->expand, get_address (msg));
4399         } else {
4400                 sur->expand_enable = false;
4401                 s = _select;
4402         }
4403
4404         return _strip_select (s, get_address (msg));
4405 }
4406
4407 int
4408 OSC::route_set_gain_dB (int ssid, float dB, lo_message msg)
4409 {
4410         if (!session) {
4411                 return -1;
4412         }
4413         OSCSurface *sur = get_surface(get_address (msg));
4414         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4415         if (s) {
4416                 float abs;
4417                 if (s->gain_control()) {
4418                         if (dB < -192) {
4419                                 abs = 0;
4420                         } else {
4421                                 abs = dB_to_coefficient (dB);
4422                                 float top = s->gain_control()->upper();
4423                                 if (abs > top) {
4424                                         abs = top;
4425                                 }
4426                         }
4427                         fake_touch (s->gain_control());
4428                         s->gain_control()->set_value (abs, sur->usegroup);
4429                         return 0;
4430                 }
4431         }
4432         return float_message_with_id (X_("/strip/gain"), ssid, -193, sur->feedback[2], get_address (msg));
4433 }
4434
4435 int
4436 OSC::sel_gain (float val, lo_message msg)
4437 {
4438         OSCSurface *sur = get_surface(get_address (msg));
4439         boost::shared_ptr<Stripable> s;
4440         if (sur->expand_enable) {
4441                 s = get_strip (sur->expand, get_address (msg));
4442         } else {
4443                 s = _select;
4444         }
4445         if (s) {
4446                 float abs;
4447                 if (s->gain_control()) {
4448                         if (val < -192) {
4449                                 abs = 0;
4450                         } else {
4451                                 abs = dB_to_coefficient (val);
4452                                 float top = s->gain_control()->upper();
4453                                 if (abs > top) {
4454                                         abs = top;
4455                                 }
4456                         }
4457                         fake_touch (s->gain_control());
4458                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
4459                         return 0;
4460                 }
4461         }
4462         return float_message(X_("/select/gain"), -193, get_address (msg));
4463 }
4464
4465 int
4466 OSC::sel_dB_delta (float delta, lo_message msg)
4467 {
4468         OSCSurface *sur = get_surface(get_address (msg));
4469         boost::shared_ptr<Stripable> s;
4470         if (sur->expand_enable) {
4471                 s = get_strip (sur->expand, get_address (msg));
4472         } else {
4473                 s = _select;
4474         }
4475         if (s) {
4476                 if (s->gain_control()) {
4477                         float dB = accurate_coefficient_to_dB (s->gain_control()->get_value()) + delta;
4478                         float abs;
4479                         if (dB < -192) {
4480                                 abs = 0;
4481                         } else {
4482                                 abs = dB_to_coefficient (dB);
4483                                 float top = s->gain_control()->upper();
4484                                 if (abs > top) {
4485                                         abs = top;
4486                                 }
4487                         }
4488                         fake_touch (s->gain_control());
4489                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
4490                         return 0;
4491                 }
4492         }
4493         return float_message(X_("/select/gain"), -193, get_address (msg));
4494 }
4495
4496 int
4497 OSC::route_set_gain_fader (int ssid, float pos, lo_message msg)
4498 {
4499         if (!session) {
4500                 return -1;
4501         }
4502         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4503         OSCSurface *sur = get_surface(get_address (msg));
4504
4505         if (s) {
4506                 if (s->gain_control()) {
4507                         fake_touch (s->gain_control());
4508                         s->gain_control()->set_value (s->gain_control()->interface_to_internal (pos), sur->usegroup);
4509                 } else {
4510                         return float_message_with_id (X_("/strip/fader"), ssid, 0, sur->feedback[2], get_address (msg));
4511                 }
4512         } else {
4513                 return float_message_with_id (X_("/strip/fader"), ssid, 0, sur->feedback[2], get_address (msg));
4514         }
4515         return 0;
4516 }
4517
4518 int
4519 OSC::strip_db_delta (int ssid, float delta, lo_message msg)
4520 {
4521         if (!session) return -1;
4522         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4523         OSCSurface *sur = get_surface(get_address (msg));
4524         if (s) {
4525                 float db = accurate_coefficient_to_dB (s->gain_control()->get_value()) + delta;
4526                 float abs;
4527                 if (db < -192) {
4528                         abs = 0;
4529                 } else {
4530                         abs = dB_to_coefficient (db);
4531                         float top = s->gain_control()->upper();
4532                         if (abs > top) {
4533                                 abs = top;
4534                         }
4535                 }
4536                 s->gain_control()->set_value (abs, sur->usegroup);
4537                 return 0;
4538         }
4539         return -1;
4540 }
4541
4542 int
4543 OSC::sel_fader (float val, lo_message msg)
4544 {
4545         OSCSurface *sur = get_surface(get_address (msg));
4546         boost::shared_ptr<Stripable> s;
4547         if (sur->expand_enable) {
4548                 s = get_strip (sur->expand, get_address (msg));
4549         } else {
4550                 s = _select;
4551         }
4552         if (s) {
4553                 if (s->gain_control()) {
4554                         fake_touch (s->gain_control());
4555                         s->gain_control()->set_value (s->gain_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
4556                         return 0;
4557                 }
4558         }
4559         return float_message(X_("/select/fader"), 0, get_address (msg));
4560 }
4561
4562 int
4563 OSC::route_set_trim_abs (int ssid, float level, lo_message msg)
4564 {
4565         if (!session) return -1;
4566         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4567         OSCSurface *sur = get_surface(get_address (msg));
4568
4569         if (s) {
4570                 if (s->trim_control()) {
4571                         s->trim_control()->set_value (level, sur->usegroup);
4572                         return 0;
4573                 }
4574
4575         }
4576
4577         return -1;
4578 }
4579
4580 int
4581 OSC::route_set_trim_dB (int ssid, float dB, lo_message msg)
4582 {
4583         OSCSurface *sur = get_surface(get_address (msg));
4584         int ret;
4585         ret = route_set_trim_abs(ssid, dB_to_coefficient (dB), msg);
4586         if (ret != 0) {
4587                 return float_message_with_id (X_("/strip/trimdB"), ssid, 0, sur->feedback[2], get_address (msg));
4588         }
4589
4590 return 0;
4591 }
4592
4593 int
4594 OSC::sel_trim (float val, lo_message msg)
4595 {
4596         OSCSurface *sur = get_surface(get_address (msg));
4597         boost::shared_ptr<Stripable> s;
4598         if (sur->expand_enable) {
4599                 s = get_strip (sur->expand, get_address (msg));
4600         } else {
4601                 s = _select;
4602         }
4603         if (s) {
4604                 if (s->trim_control()) {
4605                         s->trim_control()->set_value (dB_to_coefficient (val), PBD::Controllable::NoGroup);
4606                         return 0;
4607                 }
4608         }
4609         return float_message(X_("/select/trimdB"), 0, get_address (msg));
4610 }
4611
4612 int
4613 OSC::sel_hide (uint32_t state, lo_message msg)
4614 {
4615         OSCSurface *sur = get_surface(get_address (msg));
4616         boost::shared_ptr<Stripable> s;
4617         if (sur->expand_enable) {
4618                 s = get_strip (sur->expand, get_address (msg));
4619         } else {
4620                 s = _select;
4621         }
4622         if (s) {
4623                 if (state != s->is_hidden ()) {
4624                         s->presentation_info().set_hidden ((bool) state);
4625                 }
4626         }
4627         return 0;
4628 }
4629
4630 int
4631 OSC::sel_pan_position (float val, lo_message msg)
4632 {
4633         OSCSurface *sur = get_surface(get_address (msg));
4634         boost::shared_ptr<Stripable> s;
4635         if (sur->expand_enable) {
4636                 s = get_strip (sur->expand, get_address (msg));
4637         } else {
4638                 s = _select;
4639         }
4640         if (s) {
4641                 if(s->pan_azimuth_control()) {
4642                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
4643                         return 0;
4644                 }
4645         }
4646         return float_message(X_("/select/pan_stereo_position"), 0.5, get_address (msg));
4647 }
4648
4649 int
4650 OSC::sel_pan_width (float val, lo_message msg)
4651 {
4652         OSCSurface *sur = get_surface(get_address (msg));
4653         boost::shared_ptr<Stripable> s;
4654         if (sur->expand_enable) {
4655                 s = get_strip (sur->expand, get_address (msg));
4656         } else {
4657                 s = _select;
4658         }
4659         if (s) {
4660                 if (s->pan_width_control()) {
4661                         s->pan_width_control()->set_value (s->pan_width_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
4662                         return 0;
4663                 }
4664         }
4665         return float_message(X_("/select/pan_stereo_width"), 1, get_address (msg));
4666 }
4667
4668 int
4669 OSC::route_set_pan_stereo_position (int ssid, float pos, lo_message msg)
4670 {
4671         if (!session) return -1;
4672         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4673         OSCSurface *sur = get_surface(get_address (msg));
4674
4675         if (s) {
4676                 if(s->pan_azimuth_control()) {
4677                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (pos), sur->usegroup);
4678                         return 0;
4679                 }
4680         }
4681
4682         return float_message_with_id (X_("/strip/pan_stereo_position"), ssid, 0.5, sur->feedback[2], get_address (msg));
4683 }
4684
4685 int
4686 OSC::route_set_pan_stereo_width (int ssid, float pos, lo_message msg)
4687 {
4688         if (!session) return -1;
4689         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4690         OSCSurface *sur = get_surface(get_address (msg));
4691
4692         if (s) {
4693                 if (s->pan_width_control()) {
4694                         s->pan_width_control()->set_value (pos, sur->usegroup);
4695                         return 0;
4696                 }
4697         }
4698
4699         return float_message_with_id (X_("/strip/pan_stereo_width"), ssid, 1, sur->feedback[2], get_address (msg));
4700 }
4701
4702 int
4703 OSC::route_set_send_gain_dB (int ssid, int id, float val, lo_message msg)
4704 {
4705         if (!session) {
4706                 return -1;
4707         }
4708         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4709         OSCSurface *sur = get_surface(get_address (msg));
4710         float abs;
4711         if (s) {
4712                 if (id > 0) {
4713                         --id;
4714                 }
4715 #ifdef MIXBUS
4716                 abs = val;
4717 #else
4718                 if (val < -192) {
4719                         abs = 0;
4720                 } else {
4721                         abs = dB_to_coefficient (val);
4722                 }
4723 #endif
4724                 if (s->send_level_controllable (id)) {
4725                         s->send_level_controllable (id)->set_value (abs, sur->usegroup);
4726                         return 0;
4727                 }
4728         }
4729         return 0;
4730 }
4731
4732 int
4733 OSC::route_set_send_fader (int ssid, int id, float val, lo_message msg)
4734 {
4735         if (!session) {
4736                 return -1;
4737         }
4738         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4739         OSCSurface *sur = get_surface(get_address (msg));
4740         float abs;
4741         if (s) {
4742
4743                 if (id > 0) {
4744                         --id;
4745                 }
4746
4747                 if (s->send_level_controllable (id)) {
4748                         abs = s->send_level_controllable(id)->interface_to_internal (val);
4749                         s->send_level_controllable (id)->set_value (abs, sur->usegroup);
4750                         return 0;
4751                 }
4752         }
4753         return 0;
4754 }
4755
4756 int
4757 OSC::sel_sendgain (int id, float val, lo_message msg)
4758 {
4759         OSCSurface *sur = get_surface(get_address (msg));
4760         if (sur->send_page_size && (id > (int)sur->send_page_size)) {
4761                 return float_message_with_id (X_("/select/send_gain"), id, -193, sur->feedback[2], get_address (msg));
4762         }
4763         boost::shared_ptr<Stripable> s;
4764         if (sur->expand_enable) {
4765                 s = get_strip (sur->expand, get_address (msg));
4766         } else {
4767                 s = _select;
4768         }
4769         float abs;
4770         int send_id = 0;
4771         if (s) {
4772                 if (id > 0) {
4773                         send_id = id - 1;
4774                 }
4775 #ifdef MIXBUS
4776                 abs = val;
4777 #else
4778                 if (val < -192) {
4779                         abs = 0;
4780                 } else {
4781                         abs = dB_to_coefficient (val);
4782                 }
4783 #endif
4784                 if (sur->send_page_size) {
4785                         send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
4786                 }
4787                 if (s->send_level_controllable (send_id)) {
4788                         s->send_level_controllable (send_id)->set_value (abs, PBD::Controllable::NoGroup);
4789                         return 0;
4790                 }
4791         }
4792         return float_message_with_id (X_("/select/send_gain"), id, -193, sur->feedback[2], get_address (msg));
4793 }
4794
4795 int
4796 OSC::sel_sendfader (int id, float val, lo_message msg)
4797 {
4798         OSCSurface *sur = get_surface(get_address (msg));
4799         if (sur->send_page_size && (id > (int)sur->send_page_size)) {
4800                 return float_message_with_id (X_("/select/send_fader"), id, 0, sur->feedback[2], get_address (msg));
4801         }
4802         boost::shared_ptr<Stripable> s;
4803         if (sur->expand_enable) {
4804                 s = get_strip (sur->expand, get_address (msg));
4805         } else {
4806                 s = _select;
4807         }
4808         float abs;
4809         int send_id = 0;
4810         if (s) {
4811
4812                 if (id > 0) {
4813                         send_id = id - 1;
4814                 }
4815                 if (sur->send_page_size) {
4816                         send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
4817                 }
4818
4819                 if (s->send_level_controllable (send_id)) {
4820                         abs = s->send_level_controllable(send_id)->interface_to_internal (val);
4821                         s->send_level_controllable (send_id)->set_value (abs, PBD::Controllable::NoGroup);
4822                         return 0;
4823                 }
4824         }
4825         return float_message_with_id (X_("/select/send_fader"), id, 0, sur->feedback[2], get_address (msg));
4826 }
4827
4828 int
4829 OSC::route_set_send_enable (int ssid, int sid, float val, lo_message msg)
4830 {
4831         if (!session) {
4832                 return -1;
4833         }
4834         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
4835         OSCSurface *sur = get_surface(get_address (msg));
4836
4837         if (s) {
4838
4839                 /* revert to zero-based counting */
4840
4841                 if (sid > 0) {
4842                         --sid;
4843                 }
4844
4845                 if (s->send_enable_controllable (sid)) {
4846                         s->send_enable_controllable (sid)->set_value (val, sur->usegroup);
4847                         return 0;
4848                 }
4849
4850                 if (s->send_level_controllable (sid)) {
4851                         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
4852                         if (!r) {
4853                                 return 0;
4854                         }
4855                         boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(sid));
4856                         if (snd) {
4857                                 if (val) {
4858                                         snd->activate();
4859                                 } else {
4860                                         snd->deactivate();
4861                                 }
4862                         }
4863                         return 0;
4864                 }
4865
4866         }
4867
4868         return -1;
4869 }
4870
4871 int
4872 OSC::sel_sendenable (int id, float val, lo_message msg)
4873 {
4874         OSCSurface *sur = get_surface(get_address (msg));
4875         if (sur->send_page_size && (id > (int)sur->send_page_size)) {
4876                 return float_message_with_id (X_("/select/send_enable"), id, 0, sur->feedback[2], get_address (msg));
4877         }
4878         boost::shared_ptr<Stripable> s;
4879         if (sur->expand_enable) {
4880                 s = get_strip (sur->expand, get_address (msg));
4881         } else {
4882                 s = _select;
4883         }
4884         int send_id = 0;
4885         if (s) {
4886                 if (id > 0) {
4887                         send_id = id - 1;
4888                 }
4889                 if (sur->send_page_size) {
4890                         send_id = send_id + ((sur->send_page - 1) * sur->send_page_size);
4891                 }
4892                 if (s->send_enable_controllable (send_id)) {
4893                         s->send_enable_controllable (send_id)->set_value (val, PBD::Controllable::NoGroup);
4894                         return 0;
4895                 }
4896                 if (s->send_level_controllable (send_id)) {
4897                         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
4898                         if (!r) {
4899                                 // should never get here
4900                                 return float_message_with_id (X_("/select/send_enable"), id, 0, sur->feedback[2], get_address (msg));
4901                         }
4902                         boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(send_id));
4903                         if (snd) {
4904                                 if (val) {
4905                                         snd->activate();
4906                                 } else {
4907                                         snd->deactivate();
4908                                 }
4909                         }
4910                         return 0;
4911                 }
4912         }
4913         return float_message_with_id (X_("/select/send_enable"), id, 0, sur->feedback[2], get_address (msg));
4914 }
4915
4916 int
4917 OSC::sel_master_send_enable (int state, lo_message msg)
4918 {
4919         OSCSurface *sur = get_surface(get_address (msg));
4920         boost::shared_ptr<Stripable> s;
4921         if (sur->expand_enable) {
4922                 s = get_strip (sur->expand, get_address (msg));
4923         } else {
4924                 s = _select;
4925         }
4926         if (s) {
4927                 if (s->master_send_enable_controllable ()) {
4928                         s->master_send_enable_controllable()->set_value (state, PBD::Controllable::NoGroup);
4929                         return 0;
4930                 }
4931         }
4932         return float_message (X_("/select/master_send_enable"), 0, get_address(msg));
4933 }
4934
4935 int
4936 OSC::select_plugin_parameter (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg) {
4937         OSCSurface *sur = get_surface(get_address (msg));
4938         int paid;
4939         uint32_t piid = sur->plugin_id;
4940         float value = 0;
4941         if (argc > 1) {
4942                 // no inline args
4943                 if (argc == 2) {
4944                         // change parameter in already selected plugin
4945                         if (types[0]  == 'f') {
4946                                 paid = (int) argv[0]->f;
4947                         } else {
4948                                 paid = argv[0]->i;
4949                         }
4950                         value = argv[1]->f;
4951                 } else if (argc == 3) {
4952                         if (types[0] == 'f') {
4953                                 piid = (int) argv[0]->f;
4954                         } else {
4955                                 piid = argv[0]->i;
4956                         }
4957                         _sel_plugin (piid, get_address (msg));
4958                         if (types[1] == 'f') {
4959                                 paid = (int) argv[1]->f;
4960                         } else {
4961                                 paid = argv[1]->i;
4962                         }
4963                         value = argv[2]->f;
4964                 } else if (argc > 3) {
4965                         PBD::warning << "OSC: Too many parameters: " << argc << endmsg;
4966                         return -1;
4967                 }
4968         } else if (argc) {
4969                 const char * par = strstr (&path[25], "/");
4970                 if (par) {
4971                         piid = atoi (&path[25]);
4972                         _sel_plugin (piid, msg);
4973                         paid = atoi (&par[1]);
4974                         value = argv[0]->f;
4975                         // we have plugin id too
4976                 } else {
4977                         // just parameter
4978                         paid = atoi (&path[25]);
4979                         value = argv[0]->f;
4980                 }
4981         } else {
4982                 PBD::warning << "OSC: Must have parameters." << endmsg;
4983                 return -1;
4984         }
4985         if (!piid || piid > sur->plugins.size ()) {
4986                 return float_message_with_id (X_("/select/plugin/parameter"), paid, 0, sur->feedback[2], get_address (msg));
4987         }
4988         if (sur->plug_page_size && (paid > (int)sur->plug_page_size)) {
4989                 return float_message_with_id (X_("/select/plugin/parameter"), paid, 0, sur->feedback[2], get_address (msg));
4990         }
4991         boost::shared_ptr<Stripable> s = sur->select;
4992         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
4993         if (!r) {
4994                 return 1;
4995         }
4996
4997         boost::shared_ptr<Processor> proc = r->nth_plugin (sur->plugins[sur->plugin_id - 1]);
4998         boost::shared_ptr<PluginInsert> pi;
4999         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(proc))) {
5000                 return 1;
5001         }
5002         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5003         // paid is paged parameter convert to absolute
5004         int parid = paid + (int)sur->plug_page - 1;
5005         if (parid > (int) sur->plug_params.size ()) {
5006                 if (sur->feedback[13]) {
5007                         float_message_with_id (X_("/select/plugin/parameter"), paid, 0, sur->feedback[2], get_address (msg));
5008                 }
5009                 return 0;
5010         }
5011
5012         bool ok = false;
5013         uint32_t controlid = pip->nth_parameter(sur->plug_params[parid - 1], ok);
5014         if (!ok) {
5015                 return 1;
5016         }
5017         ParameterDescriptor pd;
5018         pip->get_parameter_descriptor(controlid, pd);
5019         if ( pip->parameter_is_input(controlid) || pip->parameter_is_control(controlid) ) {
5020                 boost::shared_ptr<AutomationControl> c = pi->automation_control(Evoral::Parameter(PluginAutomation, 0, controlid));
5021                 if (c) {
5022                         if (pd.integer_step && pd.upper == 1) {
5023                                 if (c->get_value () && value < 1.0) {
5024                                         c->set_value (0, PBD::Controllable::NoGroup);
5025                                 } else if (!c->get_value () && value) {
5026                                         c->set_value (1, PBD::Controllable::NoGroup);
5027                                 }
5028                         } else {
5029                                 c->set_value (c->interface_to_internal (value), PBD::Controllable::NoGroup);
5030                         }
5031                         return 0;
5032                 }
5033         }
5034         return 1;
5035 }
5036
5037 int
5038 OSC::sel_plugin_activate (float state, lo_message msg)
5039 {
5040         if (!session) {
5041                 return -1;
5042         }
5043         OSCSurface *sur = get_surface(get_address (msg));
5044         if (sur->plugins.size() > 0) {
5045                 boost::shared_ptr<Stripable> s = sur->select;
5046
5047                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5048
5049                 if (r) {
5050                         boost::shared_ptr<Processor> redi=r->nth_plugin (sur->plugins[sur->plugin_id -1]);
5051                         if (redi) {
5052                                 boost::shared_ptr<PluginInsert> pi;
5053                                 if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5054                                         if(state > 0) {
5055                                                 pi->activate();
5056                                         } else {
5057                                                 pi->deactivate();
5058                                         }
5059                                         return 0;
5060                                 }
5061                         }
5062                 }
5063         }
5064         float_message (X_("/select/plugin/activate"), 0, get_address (msg));
5065         PBD::warning << "OSC: Select has no Plugin." << endmsg;
5066         return 0;
5067 }
5068
5069 int
5070 OSC::route_plugin_list (int ssid, lo_message msg) {
5071         if (!session) {
5072                 return -1;
5073         }
5074
5075         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
5076
5077         if (!r) {
5078                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5079                 return -1;
5080         }
5081         int piid = 0;
5082
5083         lo_message reply = lo_message_new ();
5084         lo_message_add_int32 (reply, ssid);
5085
5086
5087         for (;;) {
5088                 boost::shared_ptr<Processor> redi = r->nth_plugin(piid);
5089                 if ( !redi ) {
5090                         break;
5091                 }
5092
5093                 boost::shared_ptr<PluginInsert> pi;
5094
5095                 if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5096                         PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5097                         continue;
5098                 }
5099                 lo_message_add_int32 (reply, piid + 1);
5100
5101                 boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5102                 lo_message_add_string (reply, pip->name());
5103                 lo_message_add_int32(reply, redi->enabled() ? 1 : 0);
5104
5105                 piid++;
5106         }
5107
5108         lo_send_message (get_address (msg), X_("/strip/plugin/list"), reply);
5109         lo_message_free (reply);
5110         return 0;
5111 }
5112
5113 int
5114 OSC::route_plugin_descriptor (int ssid, int piid, lo_message msg) {
5115         if (!session) {
5116                 return -1;
5117         }
5118
5119         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
5120
5121         if (!r) {
5122                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5123                 return -1;
5124         }
5125
5126         boost::shared_ptr<Processor> redi = r->nth_plugin(piid - 1);
5127
5128         if (!redi) {
5129                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5130                 return -1;
5131         }
5132
5133         boost::shared_ptr<PluginInsert> pi;
5134
5135         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5136                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5137                 return -1;
5138         }
5139
5140         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5141         bool ok = false;
5142
5143         for ( uint32_t ppi = 0; ppi < pip->parameter_count(); ppi++) {
5144
5145                 uint32_t controlid = pip->nth_parameter(ppi, ok);
5146                 if (!ok) {
5147                         continue;
5148                 }
5149                 boost::shared_ptr<AutomationControl> c = pi->automation_control(Evoral::Parameter(PluginAutomation, 0, controlid));
5150
5151                 lo_message reply = lo_message_new();
5152                 lo_message_add_int32 (reply, ssid);
5153                 lo_message_add_int32 (reply, piid);
5154
5155                 lo_message_add_int32 (reply, ppi + 1);
5156                 ParameterDescriptor pd;
5157                 pi->plugin()->get_parameter_descriptor(controlid, pd);
5158                 lo_message_add_string (reply, pd.label.c_str());
5159
5160                 // I've combined those binary descriptor parts in a bit-field to reduce lilo message elements
5161                 int flags = 0;
5162                 flags |= pd.enumeration ? 1 : 0;
5163                 flags |= pd.integer_step ? 2 : 0;
5164                 flags |= pd.logarithmic ? 4 : 0;
5165                 flags |= pd.sr_dependent ? 32 : 0;
5166                 flags |= pd.toggled ? 64 : 0;
5167                 flags |= pip->parameter_is_input(controlid) ? 0x80 : 0;
5168
5169                 std::string param_desc = pi->plugin()->describe_parameter(Evoral::Parameter(PluginAutomation, 0, controlid));
5170                 flags |= (param_desc == X_("hidden")) ? 0x100 : 0;
5171                 lo_message_add_int32 (reply, flags);
5172
5173                 switch(pd.datatype) {
5174                         case ARDOUR::Variant::BEATS:
5175                                 lo_message_add_string(reply, _("BEATS"));
5176                                 break;
5177                         case ARDOUR::Variant::BOOL:
5178                                 lo_message_add_string(reply, _("BOOL"));
5179                                 break;
5180                         case ARDOUR::Variant::DOUBLE:
5181                                 lo_message_add_string(reply, _("DOUBLE"));
5182                                 break;
5183                         case ARDOUR::Variant::FLOAT:
5184                                 lo_message_add_string(reply, _("FLOAT"));
5185                                 break;
5186                         case ARDOUR::Variant::INT:
5187                                 lo_message_add_string(reply, _("INT"));
5188                                 break;
5189                         case ARDOUR::Variant::LONG:
5190                                 lo_message_add_string(reply, _("LONG"));
5191                                 break;
5192                         case ARDOUR::Variant::NOTHING:
5193                                 lo_message_add_string(reply, _("NOTHING"));
5194                                 break;
5195                         case ARDOUR::Variant::PATH:
5196                                 lo_message_add_string(reply, _("PATH"));
5197                                 break;
5198                         case ARDOUR::Variant::STRING:
5199                                 lo_message_add_string(reply, _("STRING"));
5200                                 break;
5201                         case ARDOUR::Variant::URI:
5202                                 lo_message_add_string(reply, _("URI"));
5203                                 break;
5204                         default:
5205                                 lo_message_add_string(reply, _("UNKNOWN"));
5206                                 break;
5207                 }
5208                 lo_message_add_float (reply, pd.lower);
5209                 lo_message_add_float (reply, pd.upper);
5210                 lo_message_add_string (reply, pd.print_fmt.c_str());
5211                 if ( pd.scale_points ) {
5212                         lo_message_add_int32 (reply, pd.scale_points->size());
5213                         for ( ARDOUR::ScalePoints::const_iterator i = pd.scale_points->begin(); i != pd.scale_points->end(); ++i) {
5214                                 lo_message_add_float (reply, i->second);
5215                                 lo_message_add_string (reply, ((std::string)i->first).c_str());
5216                         }
5217                 }
5218                 else {
5219                         lo_message_add_int32 (reply, 0);
5220                 }
5221                 if ( c ) {
5222                         lo_message_add_double (reply, c->get_value());
5223                 }
5224                 else {
5225                         lo_message_add_double (reply, 0);
5226                 }
5227
5228                 lo_send_message (get_address (msg), X_("/strip/plugin/descriptor"), reply);
5229                 lo_message_free (reply);
5230         }
5231
5232         lo_message reply = lo_message_new ();
5233         lo_message_add_int32 (reply, ssid);
5234         lo_message_add_int32 (reply, piid);
5235         lo_send_message (get_address (msg), X_("/strip/plugin/descriptor_end"), reply);
5236         lo_message_free (reply);
5237
5238         return 0;
5239 }
5240
5241 int
5242 OSC::route_plugin_reset (int ssid, int piid, lo_message msg) {
5243         if (!session) {
5244                 return -1;
5245         }
5246
5247         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
5248
5249         if (!r) {
5250                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5251                 return -1;
5252         }
5253
5254         boost::shared_ptr<Processor> redi = r->nth_plugin(piid - 1);
5255
5256         if (!redi) {
5257                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5258                 return -1;
5259         }
5260
5261         boost::shared_ptr<PluginInsert> pi;
5262
5263         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5264                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5265                 return -1;
5266         }
5267
5268         pi->reset_parameters_to_default ();
5269
5270         return 0;
5271 }
5272
5273 int
5274 OSC::route_plugin_parameter (int ssid, int piid, int par, float val, lo_message msg)
5275 {
5276         if (!session)
5277                 return -1;
5278         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
5279
5280         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5281
5282         if (!r) {
5283                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5284                 return -1;
5285         }
5286
5287         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
5288
5289         if (!redi) {
5290                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5291                 return -1;
5292         }
5293
5294         boost::shared_ptr<PluginInsert> pi;
5295
5296         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5297                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5298                 return -1;
5299         }
5300
5301         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5302         bool ok=false;
5303
5304         uint32_t controlid = pip->nth_parameter (par - 1,ok);
5305
5306         if (!ok) {
5307                 PBD::error << "OSC: Cannot find parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "'" << endmsg;
5308                 return -1;
5309         }
5310
5311         if (!pip->parameter_is_input(controlid)) {
5312                 PBD::error << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "' is not a control input" << endmsg;
5313                 return -1;
5314         }
5315
5316         ParameterDescriptor pd;
5317         pi->plugin()->get_parameter_descriptor (controlid,pd);
5318
5319         if (val >= pd.lower && val <= pd.upper) {
5320
5321                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
5322                 // cerr << "parameter:" << redi->describe_parameter(controlid) << " val:" << val << "\n";
5323                 c->set_value (val, PBD::Controllable::NoGroup);
5324         } else {
5325                 PBD::warning << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "' is out of range" << endmsg;
5326                 PBD::info << "OSC: Valid range min=" << pd.lower << " max=" << pd.upper << endmsg;
5327         }
5328
5329         return 0;
5330 }
5331
5332 //prints to cerr only
5333 int
5334 OSC::route_plugin_parameter_print (int ssid, int piid, int par, lo_message msg)
5335 {
5336         if (!session) {
5337                 return -1;
5338         }
5339         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
5340
5341         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5342
5343         if (!r) {
5344                 return -1;
5345         }
5346
5347         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
5348
5349         if (!redi) {
5350                 return -1;
5351         }
5352
5353         boost::shared_ptr<PluginInsert> pi;
5354
5355         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5356                 return -1;
5357         }
5358
5359         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5360         bool ok=false;
5361
5362         uint32_t controlid = pip->nth_parameter (par - 1,ok);
5363
5364         if (!ok) {
5365                 return -1;
5366         }
5367
5368         ParameterDescriptor pd;
5369
5370         if (pi->plugin()->get_parameter_descriptor (controlid, pd) == 0) {
5371                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
5372
5373                 cerr << "parameter:     " << pd.label  << "\n";
5374                 if (c) {
5375                         cerr << "current value: " << c->get_value () << "\n";
5376                 } else {
5377                         cerr << "current value not available, control does not exist\n";
5378                 }
5379                 cerr << "lower value:   " << pd.lower << "\n";
5380                 cerr << "upper value:   " << pd.upper << "\n";
5381         }
5382
5383         return 0;
5384 }
5385
5386 int
5387 OSC::route_plugin_activate (int ssid, int piid, lo_message msg)
5388 {
5389         if (!session)
5390                 return -1;
5391         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
5392
5393         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5394
5395         if (!r) {
5396                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5397                 return -1;
5398         }
5399
5400         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
5401
5402         if (!redi) {
5403                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5404                 return -1;
5405         }
5406
5407         boost::shared_ptr<PluginInsert> pi;
5408
5409         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5410                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5411                 return -1;
5412         }
5413
5414         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5415         pi->activate();
5416
5417         return 0;
5418 }
5419
5420 int
5421 OSC::route_plugin_deactivate (int ssid, int piid, lo_message msg)
5422 {
5423         if (!session)
5424                 return -1;
5425         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
5426
5427         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
5428
5429         if (!r) {
5430                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
5431                 return -1;
5432         }
5433
5434         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
5435
5436         if (!redi) {
5437                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
5438                 return -1;
5439         }
5440
5441         boost::shared_ptr<PluginInsert> pi;
5442
5443         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
5444                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
5445                 return -1;
5446         }
5447
5448         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
5449         pi->deactivate();
5450
5451         return 0;
5452 }
5453
5454 // select
5455
5456 int
5457 OSC::sel_pan_elevation (float val, lo_message msg)
5458 {
5459         OSCSurface *sur = get_surface(get_address (msg));
5460         boost::shared_ptr<Stripable> s;
5461         if (sur->expand_enable) {
5462                 s = get_strip (sur->expand, get_address (msg));
5463         } else {
5464                 s = _select;
5465         }
5466         if (s) {
5467                 if (s->pan_elevation_control()) {
5468                         s->pan_elevation_control()->set_value (s->pan_elevation_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
5469                         return 0;
5470                 }
5471         }
5472         return float_message(X_("/select/pan_elevation_position"), 0, get_address (msg));
5473 }
5474
5475 int
5476 OSC::sel_pan_frontback (float val, lo_message msg)
5477 {
5478         OSCSurface *sur = get_surface(get_address (msg));
5479         boost::shared_ptr<Stripable> s;
5480         if (sur->expand_enable) {
5481                 s = get_strip (sur->expand, get_address (msg));
5482         } else {
5483                 s = _select;
5484         }
5485         if (s) {
5486                 if (s->pan_frontback_control()) {
5487                         s->pan_frontback_control()->set_value (s->pan_frontback_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
5488                         return 0;
5489                 }
5490         }
5491         return float_message(X_("/select/pan_frontback_position"), 0.5, get_address (msg));
5492 }
5493
5494 int
5495 OSC::sel_pan_lfe (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->pan_lfe_control()) {
5506                         s->pan_lfe_control()->set_value (s->pan_lfe_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
5507                         return 0;
5508                 }
5509         }
5510         return float_message(X_("/select/pan_lfe_control"), 0, get_address (msg));
5511 }
5512
5513 // compressor control
5514 int
5515 OSC::sel_comp_enable (float val, lo_message msg)
5516 {
5517         OSCSurface *sur = get_surface(get_address (msg));
5518         boost::shared_ptr<Stripable> s;
5519         if (sur->expand_enable) {
5520                 s = get_strip (sur->expand, get_address (msg));
5521         } else {
5522                 s = _select;
5523         }
5524         if (s) {
5525                 if (s->comp_enable_controllable()) {
5526                         s->comp_enable_controllable()->set_value (s->comp_enable_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5527                         return 0;
5528                 }
5529         }
5530         return float_message(X_("/select/comp_enable"), 0, get_address (msg));
5531 }
5532
5533 int
5534 OSC::sel_comp_threshold (float val, lo_message msg)
5535 {
5536         OSCSurface *sur = get_surface(get_address (msg));
5537         boost::shared_ptr<Stripable> s;
5538         if (sur->expand_enable) {
5539                 s = get_strip (sur->expand, get_address (msg));
5540         } else {
5541                 s = _select;
5542         }
5543         if (s) {
5544                 if (s->comp_threshold_controllable()) {
5545                         s->comp_threshold_controllable()->set_value (s->comp_threshold_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5546                         return 0;
5547                 }
5548         }
5549         return float_message(X_("/select/comp_threshold"), 0, get_address (msg));
5550 }
5551
5552 int
5553 OSC::sel_comp_speed (float val, lo_message msg)
5554 {
5555         OSCSurface *sur = get_surface(get_address (msg));
5556         boost::shared_ptr<Stripable> s;
5557         if (sur->expand_enable) {
5558                 s = get_strip (sur->expand, get_address (msg));
5559         } else {
5560                 s = _select;
5561         }
5562         if (s) {
5563                 if (s->comp_speed_controllable()) {
5564                         s->comp_speed_controllable()->set_value (s->comp_speed_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5565                         return 0;
5566                 }
5567         }
5568         return float_message(X_("/select/comp_speed"), 0, get_address (msg));
5569 }
5570
5571 int
5572 OSC::sel_comp_mode (float val, lo_message msg)
5573 {
5574         OSCSurface *sur = get_surface(get_address (msg));
5575         boost::shared_ptr<Stripable> s;
5576         if (sur->expand_enable) {
5577                 s = get_strip (sur->expand, get_address (msg));
5578         } else {
5579                 s = _select;
5580         }
5581         if (s) {
5582                 if (s->comp_mode_controllable()) {
5583                         s->comp_mode_controllable()->set_value (s->comp_mode_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5584                         return 0;
5585                 }
5586         }
5587         return float_message(X_("/select/comp_mode"), 0, get_address (msg));
5588 }
5589
5590 int
5591 OSC::sel_comp_makeup (float val, lo_message msg)
5592 {
5593         OSCSurface *sur = get_surface(get_address (msg));
5594         boost::shared_ptr<Stripable> s;
5595         if (sur->expand_enable) {
5596                 s = get_strip (sur->expand, get_address (msg));
5597         } else {
5598                 s = _select;
5599         }
5600         if (s) {
5601                 if (s->comp_makeup_controllable()) {
5602                         s->comp_makeup_controllable()->set_value (s->comp_makeup_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5603                         return 0;
5604                 }
5605         }
5606         return float_message(X_("/select/comp_makeup"), 0, get_address (msg));
5607 }
5608
5609 // EQ control
5610
5611 int
5612 OSC::sel_eq_enable (float val, lo_message msg)
5613 {
5614         OSCSurface *sur = get_surface(get_address (msg));
5615         boost::shared_ptr<Stripable> s;
5616         if (sur->expand_enable) {
5617                 s = get_strip (sur->expand, get_address (msg));
5618         } else {
5619                 s = _select;
5620         }
5621         if (s) {
5622                 if (s->eq_enable_controllable()) {
5623                         s->eq_enable_controllable()->set_value (s->eq_enable_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
5624                         return 0;
5625                 }
5626         }
5627         return float_message(X_("/select/eq_enable"), 0, get_address (msg));
5628 }
5629
5630 int
5631 OSC::sel_eq_hpf_freq (float val, lo_message msg)
5632 {
5633         OSCSurface *sur = get_surface(get_address (msg));
5634         boost::shared_ptr<Stripable> s;
5635         if (sur->expand_enable) {
5636                 s = get_strip (sur->expand, get_address (msg));
5637         } else {
5638                 s = _select;
5639         }
5640         if (s) {
5641                 if (s->filter_freq_controllable(true)) {
5642                         s->filter_freq_controllable(true)->set_value (s->filter_freq_controllable(true)->interface_to_internal (val), PBD::Controllable::NoGroup);
5643                         return 0;
5644                 }
5645         }
5646         return float_message(X_("/select/eq_hpf/freq"), 0, get_address (msg));
5647 }
5648
5649 int
5650 OSC::sel_eq_lpf_freq (float val, lo_message msg)
5651 {
5652         OSCSurface *sur = get_surface(get_address (msg));
5653         boost::shared_ptr<Stripable> s;
5654         if (sur->expand_enable) {
5655                 s = get_strip (sur->expand, get_address (msg));
5656         } else {
5657                 s = _select;
5658         }
5659         if (s) {
5660                 if (s->filter_freq_controllable(false)) {
5661                         s->filter_freq_controllable(false)->set_value (s->filter_freq_controllable(false)->interface_to_internal (val), PBD::Controllable::NoGroup);
5662                         return 0;
5663                 }
5664         }
5665         return float_message(X_("/select/eq_lpf/freq"), 0, get_address (msg));
5666 }
5667
5668 int
5669 OSC::sel_eq_hpf_enable (float val, lo_message msg)
5670 {
5671         OSCSurface *sur = get_surface(get_address (msg));
5672         boost::shared_ptr<Stripable> s;
5673         if (sur->expand_enable) {
5674                 s = get_strip (sur->expand, get_address (msg));
5675         } else {
5676                 s = _select;
5677         }
5678         if (s) {
5679                 if (s->filter_enable_controllable(true)) {
5680                         s->filter_enable_controllable(true)->set_value (s->filter_enable_controllable(true)->interface_to_internal (val), PBD::Controllable::NoGroup);
5681                         return 0;
5682                 }
5683         }
5684         return float_message(X_("/select/eq_hpf/enable"), 0, get_address (msg));
5685 }
5686
5687 int
5688 OSC::sel_eq_lpf_enable (float val, lo_message msg)
5689 {
5690         OSCSurface *sur = get_surface(get_address (msg));
5691         boost::shared_ptr<Stripable> s;
5692         if (sur->expand_enable) {
5693                 s = get_strip (sur->expand, get_address (msg));
5694         } else {
5695                 s = _select;
5696         }
5697         if (s) {
5698                 if (s->filter_enable_controllable(false)) {
5699                         s->filter_enable_controllable(false)->set_value (s->filter_enable_controllable(false)->interface_to_internal (val), PBD::Controllable::NoGroup);
5700                         return 0;
5701                 }
5702         }
5703         return float_message(X_("/select/eq_lpf/enable"), 0, get_address (msg));
5704 }
5705
5706 int
5707 OSC::sel_eq_hpf_slope (float val, lo_message msg)
5708 {
5709         OSCSurface *sur = get_surface(get_address (msg));
5710         boost::shared_ptr<Stripable> s;
5711         if (sur->expand_enable) {
5712                 s = get_strip (sur->expand, get_address (msg));
5713         } else {
5714                 s = _select;
5715         }
5716         if (s) {
5717                 if (s->filter_slope_controllable(true)) {
5718                         s->filter_slope_controllable(true)->set_value (s->filter_slope_controllable(true)->interface_to_internal (val), PBD::Controllable::NoGroup);
5719                         return 0;
5720                 }
5721         }
5722         return float_message(X_("/select/eq_hpf/slope"), 0, get_address (msg));
5723 }
5724
5725 int
5726 OSC::sel_eq_lpf_slope (float val, lo_message msg)
5727 {
5728         OSCSurface *sur = get_surface(get_address (msg));
5729         boost::shared_ptr<Stripable> s;
5730         if (sur->expand_enable) {
5731                 s = get_strip (sur->expand, get_address (msg));
5732         } else {
5733                 s = _select;
5734         }
5735         if (s) {
5736                 if (s->filter_slope_controllable(false)) {
5737                         s->filter_slope_controllable(false)->set_value (s->filter_slope_controllable(false)->interface_to_internal (val), PBD::Controllable::NoGroup);
5738                         return 0;
5739                 }
5740         }
5741         return float_message(X_("/select/eq_lpf/slope"), 0, get_address (msg));
5742 }
5743
5744 int
5745 OSC::sel_eq_gain (int id, float val, lo_message msg)
5746 {
5747         OSCSurface *sur = get_surface(get_address (msg));
5748         boost::shared_ptr<Stripable> s;
5749         if (sur->expand_enable) {
5750                 s = get_strip (sur->expand, get_address (msg));
5751         } else {
5752                 s = _select;
5753         }
5754         if (s) {
5755                 if (id > 0) {
5756                         --id;
5757                 }
5758                 if (s->eq_gain_controllable (id)) {
5759                         s->eq_gain_controllable (id)->set_value (s->eq_gain_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
5760                         return 0;
5761                 }
5762         }
5763         return float_message_with_id (X_("/select/eq_gain"), id + 1, 0, sur->feedback[2], get_address (msg));
5764 }
5765
5766 int
5767 OSC::sel_eq_freq (int id, float val, lo_message msg)
5768 {
5769         OSCSurface *sur = get_surface(get_address (msg));
5770         boost::shared_ptr<Stripable> s;
5771         if (sur->expand_enable) {
5772                 s = get_strip (sur->expand, get_address (msg));
5773         } else {
5774                 s = _select;
5775         }
5776         if (s) {
5777                 if (id > 0) {
5778                         --id;
5779                 }
5780                 if (s->eq_freq_controllable (id)) {
5781                         s->eq_freq_controllable (id)->set_value (s->eq_freq_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
5782                         return 0;
5783                 }
5784         }
5785         return float_message_with_id (X_("/select/eq_freq"), id + 1, 0, sur->feedback[2], get_address (msg));
5786 }
5787
5788 int
5789 OSC::sel_eq_q (int id, float val, lo_message msg)
5790 {
5791         OSCSurface *sur = get_surface(get_address (msg));
5792         boost::shared_ptr<Stripable> s;
5793         if (sur->expand_enable) {
5794                 s = get_strip (sur->expand, get_address (msg));
5795         } else {
5796                 s = _select;
5797         }
5798         if (s) {
5799                 if (id > 0) {
5800                         --id;
5801                 }
5802                 if (s->eq_q_controllable (id)) {
5803                         s->eq_q_controllable (id)->set_value (s->eq_q_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
5804                         return 0;
5805                 }
5806         }
5807         return float_message_with_id (X_("/select/eq_q"), id + 1, 0, sur->feedback[2], get_address (msg));
5808 }
5809
5810 int
5811 OSC::sel_eq_shape (int id, float val, lo_message msg)
5812 {
5813         OSCSurface *sur = get_surface(get_address (msg));
5814         boost::shared_ptr<Stripable> s;
5815         if (sur->expand_enable) {
5816                 s = get_strip (sur->expand, get_address (msg));
5817         } else {
5818                 s = _select;
5819         }
5820         if (s) {
5821                 if (id > 0) {
5822                         --id;
5823                 }
5824                 if (s->eq_shape_controllable (id)) {
5825                         s->eq_shape_controllable (id)->set_value (s->eq_shape_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
5826                         return 0;
5827                 }
5828         }
5829         return float_message_with_id (X_("/select/eq_shape"), id + 1, 0, sur->feedback[2], get_address (msg));
5830 }
5831
5832 // timer callbacks
5833 bool
5834 OSC::periodic (void)
5835 {
5836         if (observer_busy) {
5837                 return true;
5838         }
5839         if (!tick) {
5840                 Glib::usleep(100); // let flurry of signals subside
5841                 if (global_init) {
5842                         for (uint32_t it = 0; it < _surface.size(); it++) {
5843                                 OSCSurface* sur = &_surface[it];
5844                                 global_feedback (sur);
5845                         }
5846                         global_init = false;
5847                         tick = true;
5848                 }
5849                 if (bank_dirty) {
5850                         _recalcbanks ();
5851                         bank_dirty = false;
5852                         tick = true;
5853                 }
5854                 return true;
5855         }
5856
5857         if (scrub_speed != 0) {
5858                 // for those jog wheels that don't have 0 on release (touch), time out.
5859                 int64_t now = ARDOUR::get_microseconds ();
5860                 int64_t diff = now - scrub_time;
5861                 if (diff > 120000) {
5862                         scrub_speed = 0;
5863                         session->request_transport_speed (0);
5864                         // locate to the place PH was at last tick
5865                         session->request_locate (scrub_place, false);
5866                 }
5867         }
5868         for (uint32_t it = 0; it < _surface.size(); it++) {
5869                 OSCSurface* sur = &_surface[it];
5870                 OSCSelectObserver* so;
5871                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
5872                         so->tick ();
5873                 }
5874                 OSCCueObserver* co;
5875                 if ((co = dynamic_cast<OSCCueObserver*>(sur->cue_obs)) != 0) {
5876                         co->tick ();
5877                 }
5878                 OSCGlobalObserver* go;
5879                 if ((go = dynamic_cast<OSCGlobalObserver*>(sur->global_obs)) != 0) {
5880                         go->tick ();
5881                 }
5882                 for (uint32_t i = 0; i < sur->observers.size(); i++) {
5883                         OSCRouteObserver* ro;
5884                         if ((ro = dynamic_cast<OSCRouteObserver*>(sur->observers[i])) != 0) {
5885                                 ro->tick ();
5886                         }
5887                 }
5888
5889         }
5890         for (FakeTouchMap::iterator x = _touch_timeout.begin(); x != _touch_timeout.end();) {
5891                 _touch_timeout[(*x).first] = (*x).second - 1;
5892                 if (!(*x).second) {
5893                         boost::shared_ptr<ARDOUR::AutomationControl> ctrl = (*x).first;
5894                         // turn touch off
5895                         ctrl->stop_touch (ctrl->session().transport_sample());
5896                         _touch_timeout.erase (x++);
5897                 } else {
5898                         x++;
5899                 }
5900         }
5901         return true;
5902 }
5903
5904 XMLNode&
5905 OSC::get_state ()
5906 {
5907         XMLNode& node (ControlProtocol::get_state());
5908         node.set_property (X_("debugmode"), (int32_t) _debugmode); // TODO: enum2str
5909         node.set_property (X_("address-only"), address_only);
5910         node.set_property (X_("remote-port"), remote_port);
5911         node.set_property (X_("banksize"), default_banksize);
5912         node.set_property (X_("striptypes"), default_strip);
5913         node.set_property (X_("feedback"), default_feedback);
5914         node.set_property (X_("gainmode"), default_gainmode);
5915         node.set_property (X_("send-page-size"), default_send_size);
5916         node.set_property (X_("plug-page-size"), default_plugin_size);
5917         return node;
5918 }
5919
5920 int
5921 OSC::set_state (const XMLNode& node, int version)
5922 {
5923         if (ControlProtocol::set_state (node, version)) {
5924                 return -1;
5925         }
5926         int32_t debugmode;
5927         if (node.get_property (X_("debugmode"), debugmode)) {
5928                 _debugmode = OSCDebugMode (debugmode);
5929         }
5930
5931         node.get_property (X_("address-only"), address_only);
5932         node.get_property (X_("remote-port"), remote_port);
5933         node.get_property (X_("banksize"), default_banksize);
5934         node.get_property (X_("striptypes"), default_strip);
5935         node.get_property (X_("feedback"), default_feedback);
5936         node.get_property (X_("gainmode"), default_gainmode);
5937         node.get_property (X_("send-page-size"), default_send_size);
5938         node.get_property (X_("plugin-page-size"), default_plugin_size);
5939
5940         global_init = true;
5941         tick = false;
5942
5943         return 0;
5944 }
5945
5946 // predicate for sort call in get_sorted_stripables
5947 struct StripableByPresentationOrder
5948 {
5949         bool operator () (const boost::shared_ptr<Stripable> & a, const boost::shared_ptr<Stripable> & b) const
5950         {
5951                 return a->presentation_info().order() < b->presentation_info().order();
5952         }
5953
5954         bool operator () (const Stripable & a, const Stripable & b) const
5955         {
5956                 return a.presentation_info().order() < b.presentation_info().order();
5957         }
5958
5959         bool operator () (const Stripable * a, const Stripable * b) const
5960         {
5961                 return a->presentation_info().order() < b->presentation_info().order();
5962         }
5963 };
5964
5965 OSC::Sorted
5966 OSC::get_sorted_stripables(std::bitset<32> types, bool cue, uint32_t custom, Sorted my_list)
5967 {
5968         Sorted sorted;
5969         StripableList stripables;
5970         StripableList custom_list;
5971
5972         // fetch all stripables
5973         session->get_stripables (stripables);
5974         if (custom) {
5975                 uint32_t nstps = my_list.size ();
5976                 // check each custom strip to see if it still exists
5977                 boost::shared_ptr<Stripable> s;
5978                 for (uint32_t i = 0; i < nstps; i++) {
5979                         bool exists = false;
5980                         s = my_list[i];
5981                         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
5982                                 boost::shared_ptr<Stripable> sl = *it;
5983                                 if (s == sl) {
5984                                         exists = true;
5985                                         break;
5986                                 }
5987                         }
5988                         if(!exists) {
5989                                 my_list[i] = boost::shared_ptr<Stripable>();
5990                         } else {
5991                                 custom_list.push_back (s);
5992                         }
5993                 }
5994                 if (custom == 1) {
5995                         return my_list;
5996                 } else {
5997                         stripables = custom_list;
5998                 }
5999         }
6000         // Look for stripables that match bit in sur->strip_types
6001         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
6002
6003                 boost::shared_ptr<Stripable> s = *it;
6004                 if (!s) {
6005                         break;
6006                 }
6007                 if (custom == 2) {
6008                         // banking off use all valid custom strips
6009                         sorted.push_back (s);
6010                 } else
6011                 if ((!cue) && (!types[9]) && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
6012                         // do nothing... skip it
6013                 } else if (types[8] && (s->is_selected())) {
6014                         sorted.push_back (s);
6015                 } else if (types[9] && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
6016                         sorted.push_back (s);
6017                 } else if (s->is_master() || s->is_monitor() || s->is_auditioner()) {
6018                         // do nothing for these either (we add them later)
6019                 } else {
6020                         if (types[0] && boost::dynamic_pointer_cast<AudioTrack>(s)) {
6021                                 sorted.push_back (s);
6022                         } else if (types[1] && boost::dynamic_pointer_cast<MidiTrack>(s)) {
6023                                 sorted.push_back (s);
6024                         } else if (types[4] && boost::dynamic_pointer_cast<VCA>(s)) {
6025                                 sorted.push_back (s);
6026                         } else
6027 #ifdef MIXBUS
6028                         if (types[2] && Profile->get_mixbus() && s->mixbus()) {
6029                                 sorted.push_back (s);
6030                         } else
6031                         if (types[7] && boost::dynamic_pointer_cast<Route>(s) && !boost::dynamic_pointer_cast<Track>(s)) {
6032                                 if (Profile->get_mixbus() && !s->mixbus()) {
6033                                         sorted.push_back (s);
6034                                 }
6035                         } else
6036 #endif
6037                         if ((types[2] || types[3] || types[7]) && boost::dynamic_pointer_cast<Route>(s) && !boost::dynamic_pointer_cast<Track>(s)) {
6038                                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(s);
6039                                 if (!(s->presentation_info().flags() & PresentationInfo::MidiBus)) {
6040                                         // note some older sessions will show midibuses as busses
6041                                         if (r->direct_feeds_according_to_reality (session->master_out())) {
6042                                                 // this is a bus
6043                                                 if (types[2]) {
6044                                                         sorted.push_back (s);
6045                                                 }
6046                                         } else {
6047                                                 // this is an Aux out
6048                                                 if (types[7]) {
6049                                                         sorted.push_back (s);
6050                                                 }
6051                                         }
6052                                 } else if (types[3]) {
6053                                                 sorted.push_back (s);
6054                                 }
6055                         }
6056                 }
6057         }
6058         if (!custom || (custom & 0x2)) {
6059                 sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
6060         }
6061         if (!custom) {
6062                 // Master/Monitor might be anywhere... we put them at the end - Sorry ;)
6063                 if (types[5]) {
6064                         sorted.push_back (session->master_out());
6065                 }
6066                 if (types[6]) {
6067                         if (session->monitor_out()) {
6068                                 sorted.push_back (session->monitor_out());
6069                         }
6070                 }
6071         }
6072         return sorted;
6073 }
6074
6075 int
6076 OSC::cue_parse (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
6077 {
6078         OSCSurface *s = get_surface(get_address (msg), true);
6079         s->bank_size = 0;
6080         float value = 0;
6081         if (argc == 1) {
6082                 if (types[0] == 'f') {
6083                         value = argv[0]->f;
6084                 } else if (types[0] == 'i') {
6085                         value = (float) argv[0]->i;
6086                 }
6087         }
6088         int ret = 1; /* unhandled */
6089         if (!strncmp (path, X_("/cue/aux"), 8)) {
6090                 // set our Aux bus
6091                 if (argc) {
6092                         if (value) {
6093                                 ret = cue_set ((uint32_t) value, msg);
6094                         } else {
6095                                 ret = 0;
6096                         }
6097                 }
6098         }
6099         else if (!strncmp (path, X_("/cue/connect"), 12)) {
6100                 // Connect to default Aux bus
6101                 if ((!argc) || argv[0]->f || argv[0]->i) {
6102                         ret = cue_set (1, msg);
6103                 } else {
6104                         ret = 0;
6105                 }
6106         }
6107         else if (!strncmp (path, X_("/cue/next_aux"), 13)) {
6108                 // switch to next Aux bus
6109                 if ((!argc) || argv[0]->f || argv[0]->i) {
6110                         ret = cue_next (msg);
6111                 } else {
6112                         ret = 0;
6113                 }
6114         }
6115         else if (!strncmp (path, X_("/cue/previous_aux"), 17)) {
6116                 // switch to previous Aux bus
6117                 if ((!argc) || argv[0]->f || argv[0]->i) {
6118                         ret = cue_previous (msg);
6119                 } else {
6120                         ret = 0;
6121                 }
6122         }
6123         else if (!strncmp (path, X_("/cue/send/fader/"), 16) && strlen (path) > 16) {
6124                 if (argc == 1) {
6125                         int id = atoi (&path[16]);
6126                         ret = cue_send_fader (id, value, msg);
6127                 }
6128         }
6129         else if (!strncmp (path, X_("/cue/send/enable/"), 17) && strlen (path) > 17) {
6130                 if (argc == 1) {
6131                         int id = atoi (&path[17]);
6132                         ret = cue_send_enable (id, value, msg);
6133                 }
6134         }
6135         else if (!strncmp (path, X_("/cue/fader"), 10)) {
6136                 if (argc == 1) {
6137                         ret = cue_aux_fader (value, msg);
6138                 }
6139         }
6140         else if (!strncmp (path, X_("/cue/mute"), 9)) {
6141                 if (argc == 1) {
6142                         ret = cue_aux_mute (value, msg);
6143                 }
6144         }
6145
6146         return ret;
6147 }
6148
6149 int
6150 OSC::cue_set (uint32_t aux, lo_message msg)
6151 {
6152
6153         return _cue_set (aux, get_address (msg));
6154 }
6155
6156 int
6157 OSC::_cue_set (uint32_t aux, lo_address addr)
6158 {
6159         int ret = 1;
6160         OSCSurface *s = get_surface(addr, true);
6161         s->bank_size = 0;
6162         s->strip_types = 128;
6163         s->feedback = 0;
6164         s->gainmode = 1;
6165         s->cue = true;
6166         s->strips = get_sorted_stripables(s->strip_types, s->cue, false, s->custom_strips);
6167
6168         s->nstrips = s->strips.size();
6169
6170         if (aux < 1) {
6171                 aux = 1;
6172         } else if (aux > s->nstrips) {
6173                 aux = s->nstrips;
6174         }
6175         s->aux = aux;
6176         // get a list of Auxes
6177         for (uint32_t n = 0; n < s->nstrips; ++n) {
6178                 boost::shared_ptr<Stripable> stp = s->strips[n];
6179                 if (stp) {
6180                         text_message (string_compose (X_("/cue/name/%1"), n+1), stp->name(), addr);
6181                         if (aux == n+1) {
6182                                 // aux must be at least one
6183
6184                                 stp->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::_cue_set, this, aux, addr), this);
6185                                 // make a list of stripables with sends that go to this bus
6186                                 s->sends = cue_get_sorted_stripables(stp, aux, addr);
6187                                 if (s->cue_obs) {
6188                                         s->cue_obs->refresh_strip (stp, s->sends, true);
6189                                 } else {
6190                                         // start cue observer
6191                                         OSCCueObserver* co = new OSCCueObserver (*this, s);
6192                                         s->cue_obs = co;
6193                                 }
6194                                 ret = 0;
6195                         }
6196
6197                 }
6198         }
6199
6200         return ret;
6201 }
6202
6203 int
6204 OSC::cue_next (lo_message msg)
6205 {
6206         OSCSurface *s = get_surface(get_address (msg), true);
6207         int ret = 1;
6208
6209         if (!s->cue) {
6210                 ret = cue_set (1, msg);
6211         }
6212         if (s->aux < s->nstrips) {
6213                 ret = cue_set (s->aux + 1, msg);
6214         } else {
6215                 ret = cue_set (s->nstrips, msg);
6216         }
6217         return ret;
6218 }
6219
6220 int
6221 OSC::cue_previous (lo_message msg)
6222 {
6223         OSCSurface *s = get_surface(get_address (msg), true);
6224         int ret = 1;
6225         if (!s->cue) {
6226                 ret = cue_set (1, msg);
6227         }
6228         if (s->aux > 1) {
6229                 ret = cue_set (s->aux - 1, msg);
6230         } else {
6231                 ret = cue_set (1, msg);
6232         }
6233         return ret;
6234 }
6235
6236 boost::shared_ptr<Send>
6237 OSC::cue_get_send (uint32_t id, lo_address addr)
6238 {
6239         OSCSurface *s = get_surface(addr, true);
6240         if (id && s->aux > 0 && id <= s->sends.size()) {
6241                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s->sends[id - 1]);
6242                 boost::shared_ptr<Stripable> aux = get_strip (s->aux, addr);
6243                 if (r && aux) {
6244                         return r->internal_send_for (boost::dynamic_pointer_cast<Route> (aux));
6245                 }
6246         }
6247         return boost::shared_ptr<Send>();
6248
6249 }
6250
6251 int
6252 OSC::cue_aux_fader (float position, lo_message msg)
6253 {
6254         if (!session) return -1;
6255
6256         OSCSurface *sur = get_surface(get_address (msg), true);
6257         if (sur->cue) {
6258                 if (sur->aux) {
6259                         boost::shared_ptr<Stripable> s = get_strip (sur->aux, get_address (msg));
6260
6261                         if (s) {
6262                                 if (s->gain_control()) {
6263                                         s->gain_control()->set_value (s->gain_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
6264                                         return 0;
6265                                 }
6266                         }
6267                 }
6268         }
6269         float_message (X_("/cue/fader"), 0, get_address (msg));
6270         return -1;
6271 }
6272
6273 int
6274 OSC::cue_aux_mute (float state, lo_message msg)
6275 {
6276         if (!session) return -1;
6277
6278         OSCSurface *sur = get_surface(get_address (msg), true);
6279         if (sur->cue) {
6280                 if (sur->aux) {
6281                         boost::shared_ptr<Stripable> s = get_strip (sur->aux, get_address (msg));
6282                         if (s) {
6283                                 if (s->mute_control()) {
6284                                         s->mute_control()->set_value (state ? 1.0 : 0.0, PBD::Controllable::NoGroup);
6285                                         return 0;
6286                                 }
6287                         }
6288                 }
6289         }
6290         float_message (X_("/cue/mute"), 0, get_address (msg));
6291         return -1;
6292 }
6293
6294 int
6295 OSC::cue_send_fader (uint32_t id, float val, lo_message msg)
6296 {
6297         if (!session) {
6298                 return -1;
6299         }
6300         boost::shared_ptr<Send> s = cue_get_send (id, get_address (msg));
6301         if (s) {
6302                 if (s->gain_control()) {
6303                         s->gain_control()->set_value (s->gain_control()->interface_to_internal(val), PBD::Controllable::NoGroup);
6304                         return 0;
6305                 }
6306         }
6307         float_message (string_compose (X_("/cue/send/fader/%1"), id), 0, get_address (msg));
6308         return -1;
6309 }
6310
6311 int
6312 OSC::cue_send_enable (uint32_t id, float state, lo_message msg)
6313 {
6314         if (!session)
6315                 return -1;
6316         boost::shared_ptr<Send> s = cue_get_send (id, get_address (msg));
6317         if (s) {
6318                 if (state) {
6319                         s->activate ();
6320                 } else {
6321                         s->deactivate ();
6322                 }
6323                 return 0;
6324         }
6325         float_message (string_compose (X_("/cue/send/enable/%1"), id), 0, get_address (msg));
6326         return -1;
6327 }
6328
6329 // generic send message
6330 int
6331 OSC::float_message (string path, float val, lo_address addr)
6332 {
6333
6334         lo_message reply;
6335         reply = lo_message_new ();
6336         lo_message_add_float (reply, (float) val);
6337
6338         lo_send_message (addr, path.c_str(), reply);
6339         lo_message_free (reply);
6340
6341         return 0;
6342 }
6343
6344 int
6345 OSC::float_message_with_id (std::string path, uint32_t ssid, float value, bool in_line, lo_address addr)
6346 {
6347         lo_message msg = lo_message_new ();
6348         if (in_line) {
6349                 path = string_compose ("%1/%2", path, ssid);
6350         } else {
6351                 lo_message_add_int32 (msg, ssid);
6352         }
6353         lo_message_add_float (msg, value);
6354
6355         lo_send_message (addr, path.c_str(), msg);
6356         lo_message_free (msg);
6357         return 0;
6358 }
6359
6360 int
6361 OSC::int_message (string path, int val, lo_address addr)
6362 {
6363
6364         lo_message reply;
6365         reply = lo_message_new ();
6366         lo_message_add_int32 (reply, (float) val);
6367
6368         lo_send_message (addr, path.c_str(), reply);
6369         lo_message_free (reply);
6370
6371         return 0;
6372 }
6373
6374 int
6375 OSC::int_message_with_id (std::string path, uint32_t ssid, int value, bool in_line, lo_address addr)
6376 {
6377         lo_message msg = lo_message_new ();
6378         if (in_line) {
6379                 path = string_compose ("%1/%2", path, ssid);
6380         } else {
6381                 lo_message_add_int32 (msg, ssid);
6382         }
6383         lo_message_add_int32 (msg, value);
6384
6385         lo_send_message (addr, path.c_str(), msg);
6386         lo_message_free (msg);
6387         return 0;
6388 }
6389
6390 int
6391 OSC::text_message (string path, string val, lo_address addr)
6392 {
6393
6394         lo_message reply;
6395         reply = lo_message_new ();
6396         lo_message_add_string (reply, val.c_str());
6397
6398         lo_send_message (addr, path.c_str(), reply);
6399         lo_message_free (reply);
6400
6401         return 0;
6402 }
6403
6404 int
6405 OSC::text_message_with_id (std::string path, uint32_t ssid, std::string val, bool in_line, lo_address addr)
6406 {
6407         lo_message msg = lo_message_new ();
6408         if (in_line) {
6409                 path = string_compose ("%1/%2", path, ssid);
6410         } else {
6411                 lo_message_add_int32 (msg, ssid);
6412         }
6413
6414         lo_message_add_string (msg, val.c_str());
6415
6416         lo_send_message (addr, path.c_str(), msg);
6417         lo_message_free (msg);
6418         return 0;
6419 }
6420
6421 // we have to have a sorted list of stripables that have sends pointed at our aux
6422 // we can use the one in osc.cc to get an aux list
6423 OSC::Sorted
6424 OSC::cue_get_sorted_stripables(boost::shared_ptr<Stripable> aux, uint32_t id, lo_message msg)
6425 {
6426         Sorted sorted;
6427         // fetch all stripables
6428         StripableList stripables;
6429
6430         session->get_stripables (stripables);
6431
6432         // Look for stripables that have a send to aux
6433         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
6434
6435                 boost::shared_ptr<Stripable> s = *it;
6436                 // we only want routes
6437                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
6438                 if (r) {
6439                         r->processors_changed.connect  (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
6440                         boost::shared_ptr<Send> snd = r->internal_send_for (boost::dynamic_pointer_cast<Route> (aux));
6441                         if (snd) { // test for send to aux
6442                                 sorted.push_back (s);
6443                                 s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::cue_set, this, id, msg), this);
6444                         }
6445                 }
6446
6447
6448         }
6449         sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
6450
6451         return sorted;
6452 }
6453