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