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