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