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