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