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