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