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