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