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