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