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