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