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