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