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