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