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