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