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