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