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