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