OSC: Fix aux mute to check stripable exists first
[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/convert.h>
32 #include <pbd/pthread_utils.h>
33 #include <pbd/file_utils.h>
34 #include <pbd/failed_constructor.h>
35
36 #include "ardour/amp.h"
37 #include "ardour/session.h"
38 #include "ardour/route.h"
39 #include "ardour/audio_track.h"
40 #include "ardour/midi_track.h"
41 #include "ardour/monitor_control.h"
42 #include "ardour/dB.h"
43 #include "ardour/filesystem_paths.h"
44 #include "ardour/panner.h"
45 #include "ardour/plugin.h"
46 #include "ardour/plugin_insert.h"
47 #include "ardour/presentation_info.h"
48 #include "ardour/send.h"
49 #include "ardour/internal_send.h"
50 #include "ardour/phase_control.h"
51 #include "ardour/solo_isolate_control.h"
52 #include "ardour/solo_safe_control.h"
53 #include "ardour/vca_manager.h"
54
55 #include "osc_select_observer.h"
56 #include "osc.h"
57 #include "osc_controllable.h"
58 #include "osc_route_observer.h"
59 #include "osc_global_observer.h"
60 #include "osc_cue_observer.h"
61 #include "pbd/i18n.h"
62
63 using namespace ARDOUR;
64 using namespace std;
65 using namespace Glib;
66 using namespace ArdourSurface;
67
68 #include "pbd/abstract_ui.cc" // instantiate template
69
70 OSC* OSC::_instance = 0;
71
72 #ifdef DEBUG
73 static void error_callback(int num, const char *m, const char *path)
74 {
75         fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
76 }
77 #else
78 static void error_callback(int, const char *, const char *)
79 {
80
81 }
82 #endif
83
84 OSC::OSC (Session& s, uint32_t port)
85         : ControlProtocol (s, X_("Open Sound Control (OSC)"))
86         , AbstractUI<OSCUIRequest> (name())
87         , local_server (0)
88         , remote_server (0)
89         , _port(port)
90         , _ok (true)
91         , _shutdown (false)
92         , _osc_server (0)
93         , _osc_unix_server (0)
94         , _debugmode (Off)
95         , address_only (false)
96         , remote_port ("8000")
97         , default_banksize (0)
98         , default_strip (159)
99         , default_feedback (0)
100         , default_gainmode (0)
101         , tick (true)
102         , bank_dirty (false)
103         , gui (0)
104 {
105         _instance = this;
106
107         session->Exported.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::session_exported, this, _1, _2), this);
108 }
109
110 OSC::~OSC()
111 {
112         stop ();
113         tear_down_gui ();
114         _instance = 0;
115 }
116
117 void*
118 OSC::request_factory (uint32_t num_requests)
119 {
120         /* AbstractUI<T>::request_buffer_factory() is a template method only
121            instantiated in this source module. To provide something visible for
122            use in the interface/descriptor, we have this static method that is
123            template-free.
124         */
125         return request_buffer_factory (num_requests);
126 }
127
128 void
129 OSC::do_request (OSCUIRequest* req)
130 {
131         if (req->type == CallSlot) {
132
133                 call_slot (MISSING_INVALIDATOR, req->the_slot);
134
135         } else if (req->type == Quit) {
136
137                 stop ();
138         }
139 }
140
141 int
142 OSC::set_active (bool yn)
143 {
144         if (yn != active()) {
145
146                 if (yn) {
147                         if (start ()) {
148                                 return -1;
149                         }
150                 } else {
151                         if (stop ()) {
152                                 return -1;
153                         }
154                 }
155
156         }
157
158         return ControlProtocol::set_active (yn);
159 }
160
161 bool
162 OSC::get_active () const
163 {
164         return _osc_server != 0;
165 }
166
167 int
168 OSC::start ()
169 {
170         char tmpstr[255];
171
172         if (_osc_server) {
173                 /* already started */
174                 return 0;
175         }
176
177         for (int j=0; j < 20; ++j) {
178                 snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
179
180                 //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
181                 //      break;
182                 //}
183
184                 if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
185                         break;
186                 }
187
188 #ifdef DEBUG
189                 cerr << "can't get osc at port: " << _port << endl;
190 #endif
191                 _port++;
192                 continue;
193         }
194
195         if (!_osc_server) {
196                 return 1;
197         }
198
199 #ifdef ARDOUR_OSC_UNIX_SERVER
200
201         // APPEARS sluggish for now
202
203         // attempt to create unix socket server too
204
205         snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
206         int fd = mkstemp(tmpstr);
207
208         if (fd >= 0 ) {
209                 ::g_unlink (tmpstr);
210                 close (fd);
211
212                 _osc_unix_server = lo_server_new (tmpstr, error_callback);
213
214                 if (_osc_unix_server) {
215                         _osc_unix_socket_path = tmpstr;
216                 }
217         }
218 #endif
219
220         PBD::info << "OSC @ " << get_server_url () << endmsg;
221
222         std::string url_file;
223
224         if (find_file (ardour_config_search_path(), "osc_url", url_file)) {
225                 _osc_url_file = url_file;
226                 if (g_file_set_contents (_osc_url_file.c_str(), get_server_url().c_str(), -1, NULL)) {
227                         cerr << "Couldn't write '" <<  _osc_url_file << "'" <<endl;
228                 }
229         }
230
231         register_callbacks();
232
233         session_loaded (*session);
234
235         // lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
236
237         /* startup the event loop thread */
238
239         BaseUI::run ();
240
241         // start timers for metering, timecode and heartbeat.
242         // timecode and metering run at 100
243         Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
244         periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &OSC::periodic));
245         periodic_timeout->attach (main_loop()->get_context());
246
247         // catch changes to selection for GUI_select mode
248         StripableSelectionChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::gui_selection_changed, this), this);
249
250         // catch track reordering
251         // receive routes added
252         session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_routes_added, this, _1), this);
253         // receive VCAs added
254         session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_vca_added, this, _1), this);
255         // order changed
256         PresentationInfo::Change.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
257
258         _select = boost::shared_ptr<Stripable>();
259
260         return 0;
261 }
262
263 void
264 OSC::thread_init ()
265 {
266         pthread_set_name (event_loop_name().c_str());
267
268         if (_osc_unix_server) {
269                 Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
270                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_unix_server));
271                 src->attach (_main_loop->get_context());
272                 local_server = src->gobj();
273                 g_source_ref (local_server);
274         }
275
276         if (_osc_server) {
277 #ifdef PLATFORM_WINDOWS
278                 Glib::RefPtr<IOChannel> chan = Glib::IOChannel::create_from_win32_socket (lo_server_get_socket_fd (_osc_server));
279                 Glib::RefPtr<IOSource> src  = IOSource::create (chan, IO_IN|IO_HUP|IO_ERR);
280 #else
281                 Glib::RefPtr<IOSource> src  = IOSource::create (lo_server_get_socket_fd (_osc_server), IO_IN|IO_HUP|IO_ERR);
282 #endif
283                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_server));
284                 src->attach (_main_loop->get_context());
285                 remote_server = src->gobj();
286                 g_source_ref (remote_server);
287         }
288
289         PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
290         SessionEvent::create_per_thread_pool (event_loop_name(), 128);
291 }
292
293 int
294 OSC::stop ()
295 {
296         /* stop main loop */
297
298         if (local_server) {
299                 g_source_destroy (local_server);
300                 g_source_unref (local_server);
301                 local_server = 0;
302         }
303
304         if (remote_server) {
305                 g_source_destroy (remote_server);
306                 g_source_unref (remote_server);
307                 remote_server = 0;
308         }
309
310         BaseUI::quit ();
311
312         if (_osc_server) {
313                 lo_server_free (_osc_server);
314                 _osc_server = 0;
315         }
316
317         if (_osc_unix_server) {
318                 lo_server_free (_osc_unix_server);
319                 _osc_unix_server = 0;
320         }
321
322         if (!_osc_unix_socket_path.empty()) {
323                 ::g_unlink (_osc_unix_socket_path.c_str());
324         }
325
326         if (!_osc_url_file.empty() ) {
327                 ::g_unlink (_osc_url_file.c_str() );
328         }
329
330         periodic_connection.disconnect ();
331         session_connections.drop_connections ();
332         cueobserver_connections.drop_connections ();
333         // Delete any active route observers
334         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
335
336                 OSCRouteObserver* rc;
337
338                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
339                         delete *x;
340                         x = route_observers.erase (x);
341                 } else {
342                         ++x;
343                 }
344         }
345 // Should maybe do global_observers too
346         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end();) {
347
348                 OSCGlobalObserver* gc;
349
350                 if ((gc = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
351                         delete *x;
352                         x = global_observers.erase (x);
353                 } else {
354                         ++x;
355                 }
356         }
357
358 // delete select observers
359         for (uint32_t it = 0; it < _surface.size(); ++it) {
360                 OSCSurface* sur = &_surface[it];
361                 OSCSelectObserver* so;
362                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
363                         delete so;
364                 }
365         }
366
367 // delete cue observers
368         for (CueObservers::iterator x = cue_observers.begin(); x != cue_observers.end();) {
369
370                 OSCCueObserver* co;
371
372                 if ((co = dynamic_cast<OSCCueObserver*>(*x)) != 0) {
373                         delete *x;
374                         x = cue_observers.erase (x);
375                 } else {
376                         ++x;
377                 }
378         }
379
380         return 0;
381 }
382
383 void
384 OSC::register_callbacks()
385 {
386         lo_server srvs[2];
387         lo_server serv;
388
389         srvs[0] = _osc_server;
390         srvs[1] = _osc_unix_server;
391
392         for (size_t i = 0; i < 2; ++i) {
393
394                 if (!srvs[i]) {
395                         continue;
396                 }
397
398                 serv = srvs[i];
399
400
401 #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this)
402
403                 // Some controls have optional "f" for feedback or touchosc
404                 // http://hexler.net/docs/touchosc-controls-reference
405
406                 REGISTER_CALLBACK (serv, "/set_surface", "iiii", set_surface);
407                 REGISTER_CALLBACK (serv, "/set_surface/feedback", "i", set_surface_feedback);
408                 REGISTER_CALLBACK (serv, "/set_surface/bank_size", "i", set_surface_bank_size);
409                 REGISTER_CALLBACK (serv, "/set_surface/gainmode", "i", set_surface_gainmode);
410                 REGISTER_CALLBACK (serv, "/set_surface/strip_types", "i", set_surface_strip_types);
411                 REGISTER_CALLBACK (serv, "/refresh", "", refresh_surface);
412                 REGISTER_CALLBACK (serv, "/refresh", "f", refresh_surface);
413                 REGISTER_CALLBACK (serv, "/strip/list", "", routes_list);
414                 REGISTER_CALLBACK (serv, "/add_marker", "", add_marker);
415                 REGISTER_CALLBACK (serv, "/add_marker", "f", add_marker);
416                 REGISTER_CALLBACK (serv, "/access_action", "s", access_action);
417                 REGISTER_CALLBACK (serv, "/loop_toggle", "", loop_toggle);
418                 REGISTER_CALLBACK (serv, "/loop_toggle", "f", loop_toggle);
419                 REGISTER_CALLBACK (serv, "/loop_location", "ii", loop_location);
420                 REGISTER_CALLBACK (serv, "/goto_start", "", goto_start);
421                 REGISTER_CALLBACK (serv, "/goto_start", "f", goto_start);
422                 REGISTER_CALLBACK (serv, "/goto_end", "", goto_end);
423                 REGISTER_CALLBACK (serv, "/goto_end", "f", goto_end);
424                 REGISTER_CALLBACK (serv, "/rewind", "", rewind);
425                 REGISTER_CALLBACK (serv, "/rewind", "f", rewind);
426                 REGISTER_CALLBACK (serv, "/ffwd", "", ffwd);
427                 REGISTER_CALLBACK (serv, "/ffwd", "f", ffwd);
428                 REGISTER_CALLBACK (serv, "/transport_stop", "", transport_stop);
429                 REGISTER_CALLBACK (serv, "/transport_stop", "f", transport_stop);
430                 REGISTER_CALLBACK (serv, "/transport_play", "", transport_play);
431                 REGISTER_CALLBACK (serv, "/transport_play", "f", transport_play);
432                 REGISTER_CALLBACK (serv, "/transport_frame", "", transport_frame);
433                 REGISTER_CALLBACK (serv, "/transport_speed", "", transport_speed);
434                 REGISTER_CALLBACK (serv, "/record_enabled", "", record_enabled);
435                 REGISTER_CALLBACK (serv, "/set_transport_speed", "f", set_transport_speed);
436                 // locate ii is position and bool roll
437                 REGISTER_CALLBACK (serv, "/locate", "ii", locate);
438                 REGISTER_CALLBACK (serv, "/save_state", "", save_state);
439                 REGISTER_CALLBACK (serv, "/save_state", "f", save_state);
440                 REGISTER_CALLBACK (serv, "/prev_marker", "", prev_marker);
441                 REGISTER_CALLBACK (serv, "/prev_marker", "f", prev_marker);
442                 REGISTER_CALLBACK (serv, "/next_marker", "", next_marker);
443                 REGISTER_CALLBACK (serv, "/next_marker", "f", next_marker);
444                 REGISTER_CALLBACK (serv, "/undo", "", undo);
445                 REGISTER_CALLBACK (serv, "/undo", "f", undo);
446                 REGISTER_CALLBACK (serv, "/redo", "", redo);
447                 REGISTER_CALLBACK (serv, "/redo", "f", redo);
448                 REGISTER_CALLBACK (serv, "/toggle_punch_in", "", toggle_punch_in);
449                 REGISTER_CALLBACK (serv, "/toggle_punch_in", "f", toggle_punch_in);
450                 REGISTER_CALLBACK (serv, "/toggle_punch_out", "", toggle_punch_out);
451                 REGISTER_CALLBACK (serv, "/toggle_punch_out", "f", toggle_punch_out);
452                 REGISTER_CALLBACK (serv, "/rec_enable_toggle", "", rec_enable_toggle);
453                 REGISTER_CALLBACK (serv, "/rec_enable_toggle", "f", rec_enable_toggle);
454                 REGISTER_CALLBACK (serv, "/toggle_all_rec_enables", "", toggle_all_rec_enables);
455                 REGISTER_CALLBACK (serv, "/toggle_all_rec_enables", "f", toggle_all_rec_enables);
456                 REGISTER_CALLBACK (serv, "/all_tracks_rec_in", "f", all_tracks_rec_in);
457                 REGISTER_CALLBACK (serv, "/all_tracks_rec_out", "f", all_tracks_rec_out);
458                 REGISTER_CALLBACK (serv, "/cancel_all_solos", "f", cancel_all_solos);
459                 REGISTER_CALLBACK (serv, "/remove_marker", "", remove_marker_at_playhead);
460                 REGISTER_CALLBACK (serv, "/remove_marker", "f", remove_marker_at_playhead);
461                 REGISTER_CALLBACK (serv, "/jump_bars", "f", jump_by_bars);
462                 REGISTER_CALLBACK (serv, "/jump_seconds", "f", jump_by_seconds);
463                 REGISTER_CALLBACK (serv, "/mark_in", "", mark_in);
464                 REGISTER_CALLBACK (serv, "/mark_in", "f", mark_in);
465                 REGISTER_CALLBACK (serv, "/mark_out", "", mark_out);
466                 REGISTER_CALLBACK (serv, "/mark_out", "f", mark_out);
467                 REGISTER_CALLBACK (serv, "/toggle_click", "", toggle_click);
468                 REGISTER_CALLBACK (serv, "/toggle_click", "f", toggle_click);
469                 REGISTER_CALLBACK (serv, "/midi_panic", "", midi_panic);
470                 REGISTER_CALLBACK (serv, "/midi_panic", "f", midi_panic);
471                 REGISTER_CALLBACK (serv, "/toggle_roll", "", toggle_roll);
472                 REGISTER_CALLBACK (serv, "/toggle_roll", "f", toggle_roll);
473                 REGISTER_CALLBACK (serv, "/stop_forget", "", stop_forget);
474                 REGISTER_CALLBACK (serv, "/stop_forget", "f", stop_forget);
475                 REGISTER_CALLBACK (serv, "/set_punch_range", "", set_punch_range);
476                 REGISTER_CALLBACK (serv, "/set_punch_range", "f", set_punch_range);
477                 REGISTER_CALLBACK (serv, "/set_loop_range", "", set_loop_range);
478                 REGISTER_CALLBACK (serv, "/set_loop_range", "f", set_loop_range);
479                 REGISTER_CALLBACK (serv, "/set_session_range", "", set_session_range);
480                 REGISTER_CALLBACK (serv, "/set_session_range", "f", set_session_range);
481                 // /toggle_monitor_* not working (comented out)
482                 REGISTER_CALLBACK (serv, "/toggle_monitor_mute", "", toggle_monitor_mute);
483                 REGISTER_CALLBACK (serv, "/toggle_monitor_mute", "f", toggle_monitor_mute);
484                 REGISTER_CALLBACK (serv, "/toggle_monitor_dim", "", toggle_monitor_dim);
485                 REGISTER_CALLBACK (serv, "/toggle_monitor_dim", "f", toggle_monitor_dim);
486                 REGISTER_CALLBACK (serv, "/toggle_monitor_mono", "", toggle_monitor_mono);
487                 REGISTER_CALLBACK (serv, "/toggle_monitor_mono", "f", toggle_monitor_mono);
488                 REGISTER_CALLBACK (serv, "/quick_snapshot_switch", "", quick_snapshot_switch);
489                 REGISTER_CALLBACK (serv, "/quick_snapshot_switch", "f", quick_snapshot_switch);
490                 REGISTER_CALLBACK (serv, "/quick_snapshot_stay", "", quick_snapshot_stay);
491                 REGISTER_CALLBACK (serv, "/quick_snapshot_stay", "f", quick_snapshot_stay);
492                 REGISTER_CALLBACK (serv, "/fit_1_track", "", fit_1_track);
493                 REGISTER_CALLBACK (serv, "/fit_1_track", "f", fit_1_track);
494                 REGISTER_CALLBACK (serv, "/fit_2_tracks", "", fit_2_tracks);
495                 REGISTER_CALLBACK (serv, "/fit_2_tracks", "f", fit_2_tracks);
496                 REGISTER_CALLBACK (serv, "/fit_4_tracks", "", fit_4_tracks);
497                 REGISTER_CALLBACK (serv, "/fit_4_tracks", "f", fit_4_tracks);
498                 REGISTER_CALLBACK (serv, "/fit_8_tracks", "", fit_8_tracks);
499                 REGISTER_CALLBACK (serv, "/fit_8_tracks", "f", fit_8_tracks);
500                 REGISTER_CALLBACK (serv, "/fit_16_tracks", "", fit_16_tracks);
501                 REGISTER_CALLBACK (serv, "/fit_16_tracks", "f", fit_16_tracks);
502                 REGISTER_CALLBACK (serv, "/fit_32_tracks", "", fit_32_tracks);
503                 REGISTER_CALLBACK (serv, "/fit_32_tracks", "f", fit_32_tracks);
504                 REGISTER_CALLBACK (serv, "/fit_all_tracks", "", fit_all_tracks);
505                 REGISTER_CALLBACK (serv, "/fit_all_tracks", "f", fit_all_tracks);
506                 REGISTER_CALLBACK (serv, "/zoom_100_ms", "", zoom_100_ms);
507                 REGISTER_CALLBACK (serv, "/zoom_100_ms", "f", zoom_100_ms);
508                 REGISTER_CALLBACK (serv, "/zoom_1_sec", "", zoom_1_sec);
509                 REGISTER_CALLBACK (serv, "/zoom_1_sec", "f", zoom_1_sec);
510                 REGISTER_CALLBACK (serv, "/zoom_10_sec", "", zoom_10_sec);
511                 REGISTER_CALLBACK (serv, "/zoom_10_sec", "f", zoom_10_sec);
512                 REGISTER_CALLBACK (serv, "/zoom_1_min", "", zoom_1_min);
513                 REGISTER_CALLBACK (serv, "/zoom_1_min", "f", zoom_1_min);
514                 REGISTER_CALLBACK (serv, "/zoom_5_min", "", zoom_5_min);
515                 REGISTER_CALLBACK (serv, "/zoom_5_min", "f", zoom_5_min);
516                 REGISTER_CALLBACK (serv, "/zoom_10_min", "", zoom_10_min);
517                 REGISTER_CALLBACK (serv, "/zoom_10_min", "f", zoom_10_min);
518                 REGISTER_CALLBACK (serv, "/zoom_to_session", "", zoom_to_session);
519                 REGISTER_CALLBACK (serv, "/zoom_to_session", "f", zoom_to_session);
520                 REGISTER_CALLBACK (serv, "/temporal_zoom_in", "f", temporal_zoom_in);
521                 REGISTER_CALLBACK (serv, "/temporal_zoom_in", "", temporal_zoom_in);
522                 REGISTER_CALLBACK (serv, "/temporal_zoom_out", "", temporal_zoom_out);
523                 REGISTER_CALLBACK (serv, "/temporal_zoom_out", "f", temporal_zoom_out);
524                 REGISTER_CALLBACK (serv, "/scroll_up_1_track", "f", scroll_up_1_track);
525                 REGISTER_CALLBACK (serv, "/scroll_up_1_track", "", scroll_up_1_track);
526                 REGISTER_CALLBACK (serv, "/scroll_dn_1_track", "f", scroll_dn_1_track);
527                 REGISTER_CALLBACK (serv, "/scroll_dn_1_track", "", scroll_dn_1_track);
528                 REGISTER_CALLBACK (serv, "/scroll_up_1_page", "f", scroll_up_1_page);
529                 REGISTER_CALLBACK (serv, "/scroll_up_1_page", "", scroll_up_1_page);
530                 REGISTER_CALLBACK (serv, "/scroll_dn_1_page", "f", scroll_dn_1_page);
531                 REGISTER_CALLBACK (serv, "/scroll_dn_1_page", "", scroll_dn_1_page);
532                 REGISTER_CALLBACK (serv, "/bank_up", "", bank_up);
533                 REGISTER_CALLBACK (serv, "/bank_up", "f", bank_up);
534                 REGISTER_CALLBACK (serv, "/bank_down", "", bank_down);
535                 REGISTER_CALLBACK (serv, "/bank_down", "f", bank_down);
536
537                 // controls for "special" strips
538                 REGISTER_CALLBACK (serv, "/master/gain", "f", master_set_gain);
539                 REGISTER_CALLBACK (serv, "/master/fader", "f", master_set_fader);
540                 REGISTER_CALLBACK (serv, "/master/mute", "i", master_set_mute);
541                 REGISTER_CALLBACK (serv, "/master/trimdB", "f", master_set_trim);
542                 REGISTER_CALLBACK (serv, "/master/pan_stereo_position", "f", master_set_pan_stereo_position);
543                 REGISTER_CALLBACK (serv, "/monitor/gain", "f", monitor_set_gain);
544                 REGISTER_CALLBACK (serv, "/monitor/fader", "f", monitor_set_fader);
545
546                 // Controls for the Selected strip
547                 REGISTER_CALLBACK (serv, "/select/recenable", "i", sel_recenable);
548                 REGISTER_CALLBACK (serv, "/select/record_safe", "i", sel_recsafe);
549                 REGISTER_CALLBACK (serv, "/select/mute", "i", sel_mute);
550                 REGISTER_CALLBACK (serv, "/select/solo", "i", sel_solo);
551                 REGISTER_CALLBACK (serv, "/select/solo_iso", "i", sel_solo_iso);
552                 REGISTER_CALLBACK (serv, "/select/solo_safe", "i", sel_solo_safe);
553                 REGISTER_CALLBACK (serv, "/select/monitor_input", "i", sel_monitor_input);
554                 REGISTER_CALLBACK (serv, "/select/monitor_disk", "i", sel_monitor_disk);
555                 REGISTER_CALLBACK (serv, "/select/polarity", "i", sel_phase);
556                 REGISTER_CALLBACK (serv, "/select/gain", "f", sel_gain);
557                 REGISTER_CALLBACK (serv, "/select/fader", "f", sel_fader);
558                 REGISTER_CALLBACK (serv, "/select/trimdB", "f", sel_trim);
559                 REGISTER_CALLBACK (serv, "/select/pan_stereo_position", "f", sel_pan_position);
560                 REGISTER_CALLBACK (serv, "/select/pan_stereo_width", "f", sel_pan_width);
561                 REGISTER_CALLBACK (serv, "/select/send_gain", "if", sel_sendgain);
562                 REGISTER_CALLBACK (serv, "/select/send_fader", "if", sel_sendfader);
563                 REGISTER_CALLBACK (serv, "/select/send_enable", "if", sel_sendenable);
564                 REGISTER_CALLBACK (serv, "/select/expand", "i", sel_expand);
565                 REGISTER_CALLBACK (serv, "/select/pan_elevation_position", "f", sel_pan_elevation);
566                 REGISTER_CALLBACK (serv, "/select/pan_frontback_position", "f", sel_pan_frontback);
567                 REGISTER_CALLBACK (serv, "/select/pan_lfe_control", "f", sel_pan_lfe);
568                 REGISTER_CALLBACK (serv, "/select/comp_enable", "f", sel_comp_enable);
569                 REGISTER_CALLBACK (serv, "/select/comp_threshold", "f", sel_comp_threshold);
570                 REGISTER_CALLBACK (serv, "/select/comp_speed", "f", sel_comp_speed);
571                 REGISTER_CALLBACK (serv, "/select/comp_mode", "f", sel_comp_mode);
572                 REGISTER_CALLBACK (serv, "/select/comp_makeup", "f", sel_comp_makeup);
573                 REGISTER_CALLBACK (serv, "/select/eq_enable", "f", sel_eq_enable);
574                 REGISTER_CALLBACK (serv, "/select/eq_hpf", "f", sel_eq_hpf);
575                 REGISTER_CALLBACK (serv, "/select/eq_gain", "if", sel_eq_gain);
576                 REGISTER_CALLBACK (serv, "/select/eq_freq", "if", sel_eq_freq);
577                 REGISTER_CALLBACK (serv, "/select/eq_q", "if", sel_eq_q);
578                 REGISTER_CALLBACK (serv, "/select/eq_shape", "if", sel_eq_shape);
579
580                 /* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these  */ 
581                 REGISTER_CALLBACK (serv, "/strip/mute", "ii", route_mute);
582                 REGISTER_CALLBACK (serv, "/strip/solo", "ii", route_solo);
583                 REGISTER_CALLBACK (serv, "/strip/solo_iso", "ii", route_solo_iso);
584                 REGISTER_CALLBACK (serv, "/strip/solo_safe", "ii", route_solo_safe);
585                 REGISTER_CALLBACK (serv, "/strip/recenable", "ii", route_recenable);
586                 REGISTER_CALLBACK (serv, "/strip/record_safe", "ii", route_recsafe);
587                 REGISTER_CALLBACK (serv, "/strip/monitor_input", "ii", route_monitor_input);
588                 REGISTER_CALLBACK (serv, "/strip/monitor_disk", "ii", route_monitor_disk);
589                 REGISTER_CALLBACK (serv, "/strip/expand", "ii", strip_expand);
590                 REGISTER_CALLBACK (serv, "/strip/select", "ii", strip_gui_select);
591                 REGISTER_CALLBACK (serv, "/strip/polarity", "ii", strip_phase);
592                 REGISTER_CALLBACK (serv, "/strip/gain", "if", route_set_gain_dB);
593                 REGISTER_CALLBACK (serv, "/strip/fader", "if", route_set_gain_fader);
594                 REGISTER_CALLBACK (serv, "/strip/trimdB", "if", route_set_trim_dB);
595                 REGISTER_CALLBACK (serv, "/strip/pan_stereo_position", "if", route_set_pan_stereo_position);
596                 REGISTER_CALLBACK (serv, "/strip/pan_stereo_width", "if", route_set_pan_stereo_width);
597                 REGISTER_CALLBACK (serv, "/strip/plugin/parameter", "iiif", route_plugin_parameter);
598                 // prints to cerr only
599                 REGISTER_CALLBACK (serv, "/strip/plugin/parameter/print", "iii", route_plugin_parameter_print);
600                 REGISTER_CALLBACK (serv, "/strip/plugin/activate", "ii", route_plugin_activate);
601                 REGISTER_CALLBACK (serv, "/strip/plugin/deactivate", "ii", route_plugin_deactivate);
602                 REGISTER_CALLBACK (serv, "/strip/send/gain", "iif", route_set_send_gain_dB);
603                 REGISTER_CALLBACK (serv, "/strip/send/fader", "iif", route_set_send_fader);
604                 REGISTER_CALLBACK (serv, "/strip/send/enable", "iif", route_set_send_enable);
605                 REGISTER_CALLBACK(serv, "/strip/name", "is", route_rename);
606                 REGISTER_CALLBACK(serv, "/strip/sends", "i", route_get_sends);
607                 REGISTER_CALLBACK(serv, "/strip/receives", "i", route_get_receives);                
608                 REGISTER_CALLBACK(serv, "/strip/plugin/list", "i", route_plugin_list);
609                 REGISTER_CALLBACK(serv, "/strip/plugin/descriptor", "ii", route_plugin_descriptor);
610                 REGISTER_CALLBACK(serv, "/strip/plugin/reset", "ii", route_plugin_reset);
611
612                 /* still not-really-standardized query interface */
613                 //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
614                 //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
615
616                 // un/register_update args= s:ctrl s:returl s:retpath
617                 //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
618                 //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
619                 //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
620                 //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
621
622                 /* this is a special catchall handler,
623                  * register at the end so this is only called if no
624                  * other handler matches (used for debug) */
625                 lo_server_add_method (serv, 0, 0, _catchall, this);
626         }
627 }
628
629 bool
630 OSC::osc_input_handler (IOCondition ioc, lo_server srv)
631 {
632         if (ioc & ~IO_IN) {
633                 return false;
634         }
635
636         if (ioc & IO_IN) {
637                 lo_server_recv (srv);
638         }
639
640         return true;
641 }
642
643 std::string
644 OSC::get_server_url()
645 {
646         string url;
647         char * urlstr;
648
649         if (_osc_server) {
650                 urlstr = lo_server_get_url (_osc_server);
651                 url = urlstr;
652                 free (urlstr);
653         }
654
655         return url;
656 }
657
658 std::string
659 OSC::get_unix_server_url()
660 {
661         string url;
662         char * urlstr;
663
664         if (_osc_unix_server) {
665                 urlstr = lo_server_get_url (_osc_unix_server);
666                 url = urlstr;
667                 free (urlstr);
668         }
669
670         return url;
671 }
672
673 void
674 OSC::gui_changed ()
675 {
676         session->set_dirty();
677 }
678
679 void
680 OSC::listen_to_route (boost::shared_ptr<Stripable> strip, lo_address addr)
681 {
682         if (!strip) {
683                 return;
684         }
685         /* avoid duplicate listens */
686
687         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); ++x) {
688
689                 OSCRouteObserver* ro;
690
691                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
692
693                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
694
695                         if (ro->strip() == strip && res == 0) {
696                                 return;
697                         }
698                 }
699         }
700
701         OSCSurface *s = get_surface(addr);
702         uint32_t ssid = get_sid (strip, addr);
703         OSCRouteObserver* o = new OSCRouteObserver (strip, addr, ssid, s->gainmode, s->feedback);
704         route_observers.push_back (o);
705
706         strip->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::route_lost, this, boost::weak_ptr<Stripable> (strip)), this);
707 }
708
709 void
710 OSC::route_lost (boost::weak_ptr<Stripable> wr)
711 {
712         tick = false;
713         drop_route (wr);
714         bank_dirty = true;
715 }
716
717 void
718 OSC::drop_route (boost::weak_ptr<Stripable> wr)
719 {
720         boost::shared_ptr<Stripable> r = wr.lock ();
721
722         if (!r) {
723                 return;
724         }
725
726         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
727
728                 OSCRouteObserver* rc;
729
730                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
731
732                         if (rc->strip() == r) {
733                                 delete *x;
734                                 x = route_observers.erase (x);
735                         } else {
736                                 ++x;
737                         }
738                 } else {
739                         ++x;
740                 }
741         }
742 }
743
744 void
745 OSC::end_listen (boost::shared_ptr<Stripable> r, lo_address addr)
746 {
747         RouteObservers::iterator x;
748
749         // Remove the route observers
750         for (x = route_observers.begin(); x != route_observers.end();) {
751
752                 OSCRouteObserver* ro;
753
754                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
755
756                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
757
758                         if (ro->strip() == r && res == 0) {
759                                 delete *x;
760                                 x = route_observers.erase (x);
761                         }
762                         else {
763                                 ++x;
764                         }
765                 }
766                 else {
767                         ++x;
768                 }
769         }
770 }
771
772 void
773 OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg)
774 {
775         char* subpath;
776
777         subpath = (char*) malloc (len-15+1);
778         memcpy (subpath, path, len-15);
779         subpath[len-15] = '\0';
780
781         send_current_value (subpath, argv, argc, msg);
782
783         free (subpath);
784 }
785
786 void
787 OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg)
788 {
789         if (!session) {
790                 return;
791         }
792
793         lo_message reply = lo_message_new ();
794         boost::shared_ptr<Route> r;
795         int id;
796
797         lo_message_add_string (reply, path);
798
799         if (argc == 0) {
800                 lo_message_add_string (reply, "bad syntax");
801         } else {
802                 id = argv[0]->i;
803                 r = session->get_remote_nth_route (id);
804
805                 if (!r) {
806                         lo_message_add_string (reply, "not found");
807                 } else {
808
809                         if (strcmp (path, "/strip/state") == 0) {
810
811                                 if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
812                                         lo_message_add_string (reply, "AT");
813                                 } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
814                                         lo_message_add_string (reply, "MT");
815                                 } else {
816                                         lo_message_add_string (reply, "B");
817                                 }
818
819                                 lo_message_add_string (reply, r->name().c_str());
820                                 lo_message_add_int32 (reply, r->n_inputs().n_audio());
821                                 lo_message_add_int32 (reply, r->n_outputs().n_audio());
822                                 lo_message_add_int32 (reply, r->muted());
823                                 lo_message_add_int32 (reply, r->soloed());
824
825                         } else if (strcmp (path, "/strip/mute") == 0) {
826
827                                 lo_message_add_int32 (reply, (float) r->muted());
828
829                         } else if (strcmp (path, "/strip/solo") == 0) {
830
831                                 lo_message_add_int32 (reply, r->soloed());
832                         }
833                 }
834         }
835
836         lo_send_message (get_address (msg), "#reply", reply);
837         lo_message_free (reply);
838 }
839
840 int
841 OSC::_catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data)
842 {
843         return ((OSC*)user_data)->catchall (path, types, argv, argc, data);
844 }
845
846 int
847 OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
848 {
849         size_t len;
850         int ret = 1; /* unhandled */
851
852         //cerr << "Received a message, path = " << path << " types = \""
853         //     << (types ? types : "NULL") << '"' << endl;
854
855         /* 15 for /#current_value plus 2 for /<path> */
856
857         len = strlen (path);
858
859         if (len >= 17 && !strcmp (&path[len-15], "/#current_value")) {
860                 current_value_query (path, len, argv, argc, msg);
861                 ret = 0;
862
863         } else
864         if (!strncmp (path, "/cue/", 5)) {
865
866                 cue_parse (path, types, argv, argc, msg);
867
868                 ret = 0;
869         } else
870         if (strcmp (path, "/strip/listen") == 0) {
871
872                 cerr << "set up listener\n";
873
874                 lo_message reply = lo_message_new ();
875
876                 if (argc <= 0) {
877                         lo_message_add_string (reply, "syntax error");
878                 } else {
879                         for (int n = 0; n < argc; ++n) {
880
881                                 boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
882
883                                 if (!r) {
884                                         lo_message_add_string (reply, "not found");
885                                         cerr << "no such route\n";
886                                         break;
887                                 } else {
888                                         cerr << "add listener\n";
889                                         listen_to_route (r, get_address (msg));
890                                         lo_message_add_int32 (reply, argv[n]->i);
891                                 }
892                         }
893                 }
894
895                 lo_send_message (get_address (msg), "#reply", reply);
896                 lo_message_free (reply);
897
898                 ret = 0;
899
900         } else
901         if (strcmp (path, "/strip/ignore") == 0) {
902
903                 for (int n = 0; n < argc; ++n) {
904
905                         boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
906
907                         if (r) {
908                                 end_listen (r, get_address (msg));
909                         }
910                 }
911
912                 ret = 0;
913         } else
914         if (!strncmp (path, "/strip/gain/", 12) && strlen (path) > 12) {
915                 // in dB
916                 int ssid = atoi (&path[12]);
917                 route_set_gain_dB (ssid, argv[0]->f, msg);
918                 ret = 0;
919         }
920         else if (!strncmp (path, "/strip/fader/", 13) && strlen (path) > 13) {
921                 // in fader position
922                 int ssid = atoi (&path[13]);
923                 route_set_gain_fader (ssid, argv[0]->f, msg);
924                 ret = 0;
925         }
926         else if (!strncmp (path, "/strip/trimdB/", 14) && strlen (path) > 14) {
927                 int ssid = atoi (&path[14]);
928                 route_set_trim_dB (ssid, argv[0]->f, msg);
929                 ret = 0;
930         }
931         else if (!strncmp (path, "/strip/pan_stereo_position/", 27) && strlen (path) > 27) {
932                 int ssid = atoi (&path[27]);
933                 route_set_pan_stereo_position (ssid, argv[0]->f, msg);
934                 ret = 0;
935         }
936         else if (!strncmp (path, "/strip/mute/", 12) && strlen (path) > 12) {
937                 int ssid = atoi (&path[12]);
938                 route_mute (ssid, argv[0]->i, msg);
939                 ret = 0;
940         }
941         else if (!strncmp (path, "/strip/solo/", 12) && strlen (path) > 12) {
942                 int ssid = atoi (&path[12]);
943                 route_solo (ssid, argv[0]->i, msg);
944                 ret = 0;
945         }
946         else if (!strncmp (path, "/strip/monitor_input/", 21) && strlen (path) > 21) {
947                 int ssid = atoi (&path[21]);
948                 route_monitor_input (ssid, argv[0]->i, msg);
949                 ret = 0;
950         }
951         else if (!strncmp (path, "/strip/monitor_disk/", 20) && strlen (path) > 20) {
952                 int ssid = atoi (&path[20]);
953                 route_monitor_disk (ssid, argv[0]->i, msg);
954                 ret = 0;
955         }
956         else if (!strncmp (path, "/strip/recenable/", 17) && strlen (path) > 17) {
957                 int ssid = atoi (&path[17]);
958                 route_recenable (ssid, argv[0]->i, msg);
959                 ret = 0;
960         }
961         else if (!strncmp (path, "/strip/record_safe/", 19) && strlen (path) > 19) {
962                 int ssid = atoi (&path[19]);
963                 route_recsafe (ssid, argv[0]->i, msg);
964                 ret = 0;
965         }
966         else if (!strncmp (path, "/strip/expand/", 14) && strlen (path) > 14) {
967                 int ssid = atoi (&path[14]);
968                 strip_expand (ssid, argv[0]->i, msg);
969                 ret = 0;
970         }
971         else if (!strncmp (path, "/strip/select/", 14) && strlen (path) > 14) {
972                 int ssid = atoi (&path[14]);
973                 strip_gui_select (ssid, argv[0]->i, msg);
974                 ret = 0;
975         }
976         else if (!strncmp (path, "/select/send_gain/", 18) && strlen (path) > 18) {
977                 int ssid = atoi (&path[18]);
978                 sel_sendgain (ssid, argv[0]->f, msg);
979                 ret = 0;
980         }
981         else if (!strncmp (path, "/select/send_fader/", 19) && strlen (path) > 19) {
982                 int ssid = atoi (&path[19]);
983                 sel_sendfader (ssid, argv[0]->f, msg);
984                 ret = 0;
985         }
986         else if (!strncmp (path, "/select/send_enable/", 20) && strlen (path) > 20) {
987                 int ssid = atoi (&path[20]);
988                 sel_sendenable (ssid, argv[0]->f, msg);
989                 ret = 0;
990         }
991         else if (!strncmp (path, "/select/eq_gain/", 16) && strlen (path) > 16) {
992                 int ssid = atoi (&path[16]);
993                 sel_eq_gain (ssid, argv[0]->f, msg);
994                 ret = 0;
995         }
996         else if (!strncmp (path, "/select/eq_freq/", 16) && strlen (path) > 16) {
997                 int ssid = atoi (&path[16]);
998                 sel_eq_freq (ssid, argv[0]->f , msg);
999                 ret = 0;
1000         }
1001         else if (!strncmp (path, "/select/eq_q/", 13) && strlen (path) > 13) {
1002                 int ssid = atoi (&path[13]);
1003                 sel_eq_q (ssid, argv[0]->f, msg);
1004                 ret = 0;
1005         }
1006         else if (!strncmp (path, "/select/eq_shape/", 17) && strlen (path) > 17) {
1007                 int ssid = atoi (&path[17]);
1008                 sel_eq_shape (ssid, argv[0]->f, msg);
1009                 ret = 0;
1010         }
1011
1012         if ((ret && _debugmode == Unhandled)) {
1013                 debugmsg (_("Unhandled OSC message"), path, types, argv, argc);
1014         } else if ((!ret && _debugmode == All)) {
1015                 debugmsg (_("OSC"), path, types, argv, argc);
1016         }
1017
1018         return ret;
1019 }
1020
1021 void
1022 OSC::debugmsg (const char *prefix, const char *path, const char* types, lo_arg **argv, int argc)
1023 {
1024         std::stringstream ss;
1025         for (int i = 0; i < argc; ++i) {
1026                 lo_type type = (lo_type)types[i];
1027                         ss << " ";
1028                 switch (type) {
1029                         case LO_INT32:
1030                                 ss << "i:" << argv[i]->i;
1031                                 break;
1032                         case LO_FLOAT:
1033                                 ss << "f:" << argv[i]->f;
1034                                 break;
1035                         case LO_DOUBLE:
1036                                 ss << "d:" << argv[i]->d;
1037                                 break;
1038                         case LO_STRING:
1039                                 ss << "s:" << &argv[i]->s;
1040                                 break;
1041                         case LO_INT64:
1042                                 ss << "h:" << argv[i]->h;
1043                                 break;
1044                         case LO_CHAR:
1045                                 ss << "c:" << argv[i]->s;
1046                                 break;
1047                         case LO_TIMETAG:
1048                                 ss << "<Timetag>";
1049                                 break;
1050                         case LO_BLOB:
1051                                 ss << "<BLOB>";
1052                                 break;
1053                         case LO_TRUE:
1054                                 ss << "#T";
1055                                 break;
1056                         case LO_FALSE:
1057                                 ss << "#F";
1058                                 break;
1059                         case LO_NIL:
1060                                 ss << "NIL";
1061                                 break;
1062                         case LO_INFINITUM:
1063                                 ss << "#inf";
1064                                 break;
1065                         case LO_MIDI:
1066                                 ss << "<MIDI>";
1067                                 break;
1068                         case LO_SYMBOL:
1069                                 ss << "<SYMBOL>";
1070                                 break;
1071                         default:
1072                                 ss << "< ?? >";
1073                                 break;
1074                 }
1075         }
1076         PBD::info << prefix << ": " << path << ss.str() << endmsg;
1077 }
1078
1079 // "Application Hook" Handlers //
1080 void
1081 OSC::session_loaded (Session& s)
1082 {
1083 //      lo_address listener = lo_address_new (NULL, "7770");
1084 //      lo_send (listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str());
1085 }
1086
1087 void
1088 OSC::session_exported (std::string path, std::string name)
1089 {
1090         lo_address listener = lo_address_new (NULL, "7770");
1091         lo_send (listener, "/session/exported", "ss", path.c_str(), name.c_str());
1092         lo_address_free (listener);
1093 }
1094
1095 // end "Application Hook" Handlers //
1096
1097 /* path callbacks */
1098
1099 int
1100 OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, void */*data*/, void* /*user_data*/)
1101 {
1102 #if 0
1103         const char* returl;
1104
1105         if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != s) {
1106                 return 1;
1107         }
1108
1109         const char *returl = argv[1]->s;
1110         lo_address addr = find_or_cache_addr (returl);
1111
1112         const char *retpath = argv[2]->s;
1113
1114
1115         if (strcmp (argv[0]->s, "transport_frame") == 0) {
1116
1117                 if (session) {
1118                         lo_send (addr, retpath, "i", session->transport_frame());
1119                 }
1120
1121         } else if (strcmp (argv[0]->s, "transport_speed") == 0) {
1122
1123                 if (session) {
1124                         lo_send (addr, retpath, "i", session->transport_frame());
1125                 }
1126
1127         } else if (strcmp (argv[0]->s, "transport_locked") == 0) {
1128
1129                 if (session) {
1130                         lo_send (addr, retpath, "i", session->transport_frame());
1131                 }
1132
1133         } else if (strcmp (argv[0]->s, "punch_in") == 0) {
1134
1135                 if (session) {
1136                         lo_send (addr, retpath, "i", session->transport_frame());
1137                 }
1138
1139         } else if (strcmp (argv[0]->s, "punch_out") == 0) {
1140
1141                 if (session) {
1142                         lo_send (addr, retpath, "i", session->transport_frame());
1143                 }
1144
1145         } else if (strcmp (argv[0]->s, "rec_enable") == 0) {
1146
1147                 if (session) {
1148                         lo_send (addr, retpath, "i", session->transport_frame());
1149                 }
1150
1151         } else {
1152
1153                 /* error */
1154         }
1155 #endif
1156         return 0;
1157 }
1158
1159 void
1160 OSC::routes_list (lo_message msg)
1161 {
1162         if (!session) {
1163                 return;
1164         }
1165         for (int n = 0; n < (int) session->nroutes(); ++n) {
1166
1167                 boost::shared_ptr<Route> r = session->get_remote_nth_route (n);
1168
1169                 if (r) {
1170
1171                         lo_message reply = lo_message_new ();
1172
1173                         if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
1174                                 lo_message_add_string (reply, "AT");
1175                         } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
1176                                 lo_message_add_string (reply, "MT");
1177                         } else {
1178                                 lo_message_add_string (reply, "B");
1179                         }
1180
1181                         lo_message_add_string (reply, r->name().c_str());
1182                         lo_message_add_int32 (reply, r->n_inputs().n_audio());
1183                         lo_message_add_int32 (reply, r->n_outputs().n_audio());
1184                         lo_message_add_int32 (reply, r->muted());
1185                         lo_message_add_int32 (reply, r->soloed());
1186                         /* XXX Can only use order at this point */
1187                         //lo_message_add_int32 (reply, r->presentation_info().order());
1188                         // try this instead.
1189                         lo_message_add_int32 (reply, get_sid (r, get_address (msg)));
1190
1191                         if (boost::dynamic_pointer_cast<AudioTrack>(r)
1192                                         || boost::dynamic_pointer_cast<MidiTrack>(r)) {
1193
1194                                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
1195                                 lo_message_add_int32 (reply, (int32_t) t->rec_enable_control()->get_value());
1196                         }
1197
1198                         //Automatically listen to routes listed
1199                         listen_to_route(r, get_address (msg));
1200
1201                         lo_send_message (get_address (msg), "#reply", reply);
1202                         lo_message_free (reply);
1203                 }
1204         }
1205
1206         // Send end of listing message
1207         lo_message reply = lo_message_new ();
1208
1209         lo_message_add_string (reply, "end_route_list");
1210         lo_message_add_int64 (reply, session->frame_rate());
1211         lo_message_add_int64 (reply, session->current_end_frame());
1212
1213         lo_send_message (get_address (msg), "#reply", reply);
1214
1215         lo_message_free (reply);
1216 }
1217
1218 int
1219 OSC::cancel_all_solos ()
1220 {
1221         session->cancel_all_solo ();
1222         return 0;
1223 }
1224
1225 lo_address
1226 OSC::get_address (lo_message msg)
1227 {
1228         if (address_only) {
1229                 lo_address addr = lo_message_get_source (msg);
1230                 string host = lo_address_get_hostname (addr);
1231                 int protocol = lo_address_get_protocol (addr);
1232                 return lo_address_new_with_proto (protocol, host.c_str(), remote_port.c_str());
1233         } else {
1234                 return lo_message_get_source (msg);
1235         }
1236 }
1237
1238 int
1239 OSC::refresh_surface (lo_message msg)
1240 {
1241         if (address_only) {
1242                 // get rid of all surfaces and observers.
1243                 clear_devices();
1244         }
1245         OSCSurface *s = get_surface(get_address (msg));
1246         // restart all observers
1247         set_surface (s->bank_size, (uint32_t) s->strip_types.to_ulong(), (uint32_t) s->feedback.to_ulong(), (uint32_t) s->gainmode, msg);
1248         return 0;
1249 }
1250
1251 void
1252 OSC::clear_devices ()
1253 {
1254         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
1255
1256                 OSCRouteObserver* rc;
1257
1258                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
1259                         delete *x;
1260                         x = route_observers.erase (x);
1261                 } else {
1262                         ++x;
1263                 }
1264                 // slow devices need time to clear buffers
1265                 usleep ((uint32_t) 10);
1266         }
1267         // Should maybe do global_observers too
1268         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end();) {
1269
1270                 OSCGlobalObserver* gc;
1271
1272                 if ((gc = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
1273                         delete *x;
1274                         x = global_observers.erase (x);
1275                 } else {
1276                         ++x;
1277                 }
1278         }
1279         // delete select observers
1280         for (uint32_t it = 0; it < _surface.size(); ++it) {
1281                 OSCSurface* sur = &_surface[it];
1282                 OSCSelectObserver* so;
1283                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
1284                         delete so;
1285                 }
1286         }
1287         // clear out surfaces
1288         _surface.clear();
1289 }
1290
1291 int
1292 OSC::set_surface (uint32_t b_size, uint32_t strips, uint32_t fb, uint32_t gm, lo_message msg)
1293 {
1294         OSCSurface *s = get_surface(get_address (msg));
1295         s->bank_size = b_size;
1296         s->strip_types = strips;
1297         s->feedback = fb;
1298         s->gainmode = gm;
1299         // set bank and strip feedback
1300         set_bank(s->bank, msg);
1301
1302         global_feedback (s->feedback, get_address (msg), s->gainmode);
1303         return 0;
1304 }
1305
1306 int
1307 OSC::set_surface_bank_size (uint32_t bs, lo_message msg)
1308 {
1309         OSCSurface *s = get_surface(get_address (msg));
1310         s->bank_size = bs;
1311
1312         // set bank and strip feedback
1313         set_bank(s->bank, msg);
1314         return 0;
1315 }
1316
1317 int
1318 OSC::set_surface_strip_types (uint32_t st, lo_message msg)
1319 {
1320         OSCSurface *s = get_surface(get_address (msg));
1321         s->strip_types = st;
1322
1323         // set bank and strip feedback
1324         set_bank(s->bank, msg);
1325         return 0;
1326 }
1327
1328
1329 int
1330 OSC::set_surface_feedback (uint32_t fb, lo_message msg)
1331 {
1332         OSCSurface *s = get_surface(get_address (msg));
1333         s->feedback = fb;
1334
1335         // set bank and strip feedback
1336         set_bank(s->bank, msg);
1337
1338         // Set global/master feedback
1339         global_feedback (s->feedback, get_address (msg), s->gainmode);
1340         return 0;
1341 }
1342
1343
1344 int
1345 OSC::set_surface_gainmode (uint32_t gm, lo_message msg)
1346 {
1347         OSCSurface *s = get_surface(get_address (msg));
1348         s->gainmode = gm;
1349
1350         // set bank and strip feedback
1351         set_bank(s->bank, msg);
1352
1353         // Set global/master feedback
1354         global_feedback (s->feedback, get_address (msg), s->gainmode);
1355         return 0;
1356 }
1357
1358 OSC::OSCSurface *
1359 OSC::get_surface (lo_address addr)
1360 {
1361         string r_url;
1362         char * rurl;
1363         rurl = lo_address_get_url (addr);
1364         r_url = rurl;
1365         free (rurl);
1366         for (uint32_t it = 0; it < _surface.size(); ++it) {
1367                 //find setup for this server
1368                 if (!_surface[it].remote_url.find(r_url)){
1369                         return &_surface[it];
1370                 }
1371         }
1372         // if we do this when OSC is started we get the wrong stripable
1373         // we don't need this until we actually have a surface to deal with
1374         if (!_select || (_select != ControlProtocol::first_selected_stripable())) {
1375                 gui_selection_changed();
1376         }
1377
1378         // No surface create one with default values
1379         OSCSurface s;
1380         s.remote_url = r_url;
1381         s.bank = 1;
1382         s.bank_size = default_banksize; // need to find out how many strips there are
1383         s.strip_types = default_strip; // 159 is tracks, busses, and VCAs (no master/monitor)
1384         s.feedback = default_feedback;
1385         s.gainmode = default_gainmode;
1386         s.sel_obs = 0;
1387         s.expand = 0;
1388         s.expand_enable = false;
1389         s.strips = get_sorted_stripables(s.strip_types);
1390
1391         s.nstrips = s.strips.size();
1392         _surface.push_back (s);
1393
1394         return &_surface[_surface.size() - 1];
1395 }
1396
1397 // setup global feedback for a surface
1398 void
1399 OSC::global_feedback (bitset<32> feedback, lo_address addr, uint32_t gainmode)
1400 {
1401         // first destroy global observer for this surface
1402         GlobalObservers::iterator x;
1403         for (x = global_observers.begin(); x != global_observers.end();) {
1404
1405                 OSCGlobalObserver* ro;
1406
1407                 if ((ro = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
1408
1409                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
1410
1411                         if (res == 0) {
1412                                 delete *x;
1413                                 x = global_observers.erase (x);
1414                         } else {
1415                                 ++x;
1416                         }
1417                 } else {
1418                         ++x;
1419                 }
1420         }
1421         if (feedback[4] || feedback[3] || feedback[5] || feedback[6]) {
1422                 // create a new Global Observer for this surface
1423                 OSCGlobalObserver* o = new OSCGlobalObserver (*session, addr, gainmode, /*s->*/feedback);
1424                 global_observers.push_back (o);
1425         }
1426 }
1427
1428 void
1429 OSC::notify_routes_added (ARDOUR::RouteList &)
1430 {
1431         // not sure if we need this PI change seems to cover
1432         //recalcbanks();
1433 }
1434
1435 void
1436 OSC::notify_vca_added (ARDOUR::VCAList &)
1437 {
1438         // not sure if we need this PI change seems to cover
1439         //recalcbanks();
1440 }
1441
1442 void
1443 OSC::recalcbanks ()
1444 {
1445         tick = false;
1446         bank_dirty = true;
1447 }
1448
1449 void
1450 OSC::_recalcbanks ()
1451 {
1452         if (!_select || (_select != ControlProtocol::first_selected_stripable())) {
1453                 _select = ControlProtocol::first_selected_stripable();
1454         }
1455
1456         // do a set_bank for each surface we know about.
1457         for (uint32_t it = 0; it < _surface.size(); ++it) {
1458                 OSCSurface* sur = &_surface[it];
1459                 // find lo_address
1460                 lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
1461                 if (sur->cue) {
1462                         _cue_set (sur->aux, addr);
1463                 } else {
1464                         _set_bank (sur->bank, addr);
1465                 }
1466         }
1467 }
1468
1469 /*
1470  * This gets called not only when bank changes but also:
1471  *  - bank size change
1472  *  - feedback change
1473  *  - strip types changes
1474  *  - fadermode changes
1475  *  - stripable creation/deletion/flag
1476  *  - to refresh what is "displayed"
1477  * Basically any time the bank needs to be rebuilt
1478  */
1479 int
1480 OSC::set_bank (uint32_t bank_start, lo_message msg)
1481 {
1482         return _set_bank (bank_start, get_address (msg));
1483 }
1484
1485 // set bank is callable with either message or address
1486 int
1487 OSC::_set_bank (uint32_t bank_start, lo_address addr)
1488 {
1489         if (!session) {
1490                 return -1;
1491         }
1492         // no nstripables yet
1493         if (!session->nroutes()) {
1494                 return -1;
1495         }
1496
1497         OSCSurface *s = get_surface (addr);
1498
1499         // revert any expand to select
1500          s->expand = 0;
1501          s->expand_enable = false;
1502         _strip_select (ControlProtocol::first_selected_stripable(), addr);
1503
1504         // undo all listeners for this url
1505         StripableList stripables;
1506         session->get_stripables (stripables);
1507         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
1508
1509                 boost::shared_ptr<Stripable> stp = *it;
1510                 if (stp) {
1511                         end_listen (stp, addr);
1512                 }
1513                 // slow devices need time to clear buffers
1514                 usleep ((uint32_t) 10);
1515         }
1516
1517         s->strips = get_sorted_stripables(s->strip_types);
1518         s->nstrips = s->strips.size();
1519
1520         uint32_t b_size;
1521         if (!s->bank_size) {
1522                 // no banking - bank includes all stripables
1523                 b_size = s->nstrips;
1524         } else {
1525                 b_size = s->bank_size;
1526         }
1527
1528         // Do limits checking
1529         if (bank_start < 1) bank_start = 1;
1530         if (b_size >= s->nstrips)  {
1531                 bank_start = 1;
1532         } else if (bank_start > ((s->nstrips - b_size) + 1)) {
1533                 // top bank is always filled if there are enough strips for at least one bank
1534                 bank_start = (uint32_t)((s->nstrips - b_size) + 1);
1535         }
1536         //save bank in case we have had to change it
1537         s->bank = bank_start;
1538
1539         if (s->feedback[0] || s->feedback[1]) {
1540
1541                 for (uint32_t n = bank_start; n < (min ((b_size + bank_start), s->nstrips + 1)); ++n) {
1542                         if (n <= s->strips.size()) {
1543                                 boost::shared_ptr<Stripable> stp = s->strips[n - 1];
1544
1545                                 if (stp) {
1546                                         listen_to_route(stp, addr);
1547                                 }
1548                         }
1549                         // slow devices need time to clear buffers
1550                         usleep ((uint32_t) 10);
1551                 }
1552         }
1553         // light bankup or bankdown buttons if it is possible to bank in that direction
1554         if (s->feedback[4]) {
1555                 // these two messages could be bundled
1556                 lo_message reply;
1557                 reply = lo_message_new ();
1558                 if ((s->bank > (s->nstrips - s->bank_size)) || (s->nstrips < s->bank_size)) {
1559                         lo_message_add_int32 (reply, 0);
1560                 } else {
1561                         lo_message_add_int32 (reply, 1);
1562                 }
1563                 lo_send_message (addr, "/bank_up", reply);
1564                 lo_message_free (reply);
1565                 reply = lo_message_new ();
1566                 if (s->bank > 1) {
1567                         lo_message_add_int32 (reply, 1);
1568                 } else {
1569                         lo_message_add_int32 (reply, 0);
1570                 }
1571                 lo_send_message (addr, "/bank_down", reply);
1572                 lo_message_free (reply);
1573         }
1574         bank_dirty = false;
1575         tick = true;
1576         return 0;
1577 }
1578
1579 int
1580 OSC::bank_up (lo_message msg)
1581 {
1582         if (!session) {
1583                 return -1;
1584         }
1585         OSCSurface *s = get_surface(get_address (msg));
1586         set_bank (s->bank + s->bank_size, msg);
1587         return 0;
1588 }
1589
1590 int
1591 OSC::bank_down (lo_message msg)
1592 {
1593         if (!session) {
1594                 return -1;
1595         }
1596         OSCSurface *s = get_surface(get_address (msg));
1597         if (s->bank < s->bank_size) {
1598                 set_bank (1, msg);
1599         } else {
1600                 set_bank (s->bank - s->bank_size, msg);
1601         }
1602         return 0;
1603 }
1604
1605 uint32_t
1606 OSC::get_sid (boost::shared_ptr<ARDOUR::Stripable> strip, lo_address addr)
1607 {
1608         if (!strip) {
1609                 return 0;
1610         }
1611
1612         OSCSurface *s = get_surface(addr);
1613
1614         uint32_t b_size;
1615         if (!s->bank_size) {
1616                 // no banking
1617                 b_size = s->nstrips;
1618         } else {
1619                 b_size = s->bank_size;
1620         }
1621
1622         for (uint32_t n = s->bank; n < (min ((b_size + s->bank), s->nstrips + 1)); ++n) {
1623                 if (n <= s->strips.size()) {
1624                         if (strip == s->strips[n-1]) {
1625                                 return n - s->bank + 1;
1626                         }
1627                 }
1628         }
1629         // failsafe... should never get here.
1630         return 0;
1631 }
1632
1633 boost::shared_ptr<ARDOUR::Stripable>
1634 OSC::get_strip (uint32_t ssid, lo_address addr)
1635 {
1636         OSCSurface *s = get_surface(addr);
1637         if (ssid && ((ssid + s->bank - 2) < s->nstrips)) {
1638                 return s->strips[ssid + s->bank - 2];
1639         }
1640         // guess it is out of range
1641         return boost::shared_ptr<ARDOUR::Stripable>();
1642 }
1643
1644 void
1645 OSC::transport_frame (lo_message msg)
1646 {
1647         if (!session) {
1648                 return;
1649         }
1650         framepos_t pos = session->transport_frame ();
1651
1652         lo_message reply = lo_message_new ();
1653         lo_message_add_int64 (reply, pos);
1654
1655         lo_send_message (get_address (msg), "/transport_frame", reply);
1656
1657         lo_message_free (reply);
1658 }
1659
1660 void
1661 OSC::transport_speed (lo_message msg)
1662 {
1663         if (!session) {
1664                 return;
1665         }
1666         double ts = session->transport_speed ();
1667
1668         lo_message reply = lo_message_new ();
1669         lo_message_add_double (reply, ts);
1670
1671         lo_send_message (get_address (msg), "/transport_speed", reply);
1672
1673         lo_message_free (reply);
1674 }
1675
1676 void
1677 OSC::record_enabled (lo_message msg)
1678 {
1679         if (!session) {
1680                 return;
1681         }
1682         int re = (int)session->get_record_enabled ();
1683
1684         lo_message reply = lo_message_new ();
1685         lo_message_add_int32 (reply, re);
1686
1687         lo_send_message (get_address (msg), "/record_enabled", reply);
1688
1689         lo_message_free (reply);
1690 }
1691
1692 // master and monitor calls
1693 int
1694 OSC::master_set_gain (float dB)
1695 {
1696         if (!session) return -1;
1697         boost::shared_ptr<Stripable> s = session->master_out();
1698         if (s) {
1699                 if (dB < -192) {
1700                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
1701                 } else {
1702                         s->gain_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1703                 }
1704         }
1705         return 0;
1706 }
1707
1708 int
1709 OSC::master_set_fader (float position)
1710 {
1711         if (!session) return -1;
1712         boost::shared_ptr<Stripable> s = session->master_out();
1713         if (s) {
1714                 s->gain_control()->set_value (slider_position_to_gain_with_max (position, 2.0), PBD::Controllable::NoGroup);
1715         }
1716         return 0;
1717 }
1718
1719 int
1720 OSC::master_set_trim (float dB)
1721 {
1722         if (!session) return -1;
1723         boost::shared_ptr<Stripable> s = session->master_out();
1724
1725         if (s) {
1726                 s->trim_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1727         }
1728
1729         return 0;
1730 }
1731
1732 int
1733 OSC::master_set_pan_stereo_position (float position, lo_message msg)
1734 {
1735         if (!session) return -1;
1736
1737         float endposition = .5;
1738         boost::shared_ptr<Stripable> s = session->master_out();
1739
1740         if (s) {
1741                 if (s->pan_azimuth_control()) {
1742                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (position), PBD::Controllable::NoGroup);
1743                         endposition = s->pan_azimuth_control()->internal_to_interface (s->pan_azimuth_control()->get_value ());
1744                 }
1745         }
1746         OSCSurface *sur = get_surface(get_address (msg));
1747
1748         if (sur->feedback[4]) {
1749                 lo_message reply = lo_message_new ();
1750                 lo_message_add_float (reply, endposition);
1751
1752                 lo_send_message (get_address (msg), "/master/pan_stereo_position", reply);
1753                 lo_message_free (reply);
1754         }
1755
1756         return 0;
1757 }
1758
1759 int
1760 OSC::master_set_mute (uint32_t state)
1761 {
1762         if (!session) return -1;
1763
1764         boost::shared_ptr<Stripable> s = session->master_out();
1765
1766         if (s) {
1767                 s->mute_control()->set_value (state, PBD::Controllable::NoGroup);
1768         }
1769
1770         return 0;
1771 }
1772
1773 int
1774 OSC::monitor_set_gain (float dB)
1775 {
1776         if (!session) return -1;
1777         boost::shared_ptr<Stripable> s = session->monitor_out();
1778
1779         if (s) {
1780                 if (dB < -192) {
1781                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
1782                 } else {
1783                         s->gain_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1784                 }
1785         }
1786         return 0;
1787 }
1788
1789 int
1790 OSC::monitor_set_fader (float position)
1791 {
1792         if (!session) return -1;
1793         boost::shared_ptr<Stripable> s = session->monitor_out();
1794         if (s) {
1795                 s->gain_control()->set_value (slider_position_to_gain_with_max (position, 2.0), PBD::Controllable::NoGroup);
1796         }
1797         return 0;
1798 }
1799
1800 int
1801 OSC::route_get_sends(lo_message msg) {
1802         if (!session) {
1803                 return -1;
1804         }
1805
1806         lo_arg **argv = lo_message_get_argv(msg);
1807
1808         int rid = argv[0]->i;
1809
1810         boost::shared_ptr<Stripable> strip = get_strip(rid, get_address(msg));
1811         if (!strip) {
1812                 return -1;
1813         }
1814
1815         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (strip);
1816         if (!r) {
1817                 return -1;
1818         }
1819
1820         lo_message reply = lo_message_new();
1821         lo_message_add_int32(reply, rid);
1822
1823         int i = 0;
1824         for (;;) {
1825                 boost::shared_ptr<Processor> p = r->nth_send(i++);
1826
1827                 if (!p) {
1828                         break;
1829                 }
1830
1831                 boost::shared_ptr<InternalSend> isend = boost::dynamic_pointer_cast<InternalSend> (p);
1832                 if (isend) {
1833                         lo_message_add_int32(reply, get_sid(isend->target_route(), get_address(msg)));
1834                         lo_message_add_string(reply, isend->name().c_str());
1835                         lo_message_add_int32(reply, i);
1836                         boost::shared_ptr<Amp> a = isend->amp();
1837                         lo_message_add_float(reply, gain_to_slider_position(a->gain_control()->get_value()));
1838                         lo_message_add_int32(reply, p->active() ? 1 : 0);
1839                 }
1840         }
1841         // if used dedicated message path to identify this reply in async operation. Naming it #reply wont help the client to identify the content.
1842         lo_send_message(get_address (msg), "/strip/sends", reply);
1843
1844         lo_message_free(reply);
1845
1846         return 0;
1847 }
1848
1849 int
1850 OSC::route_get_receives(lo_message msg) {
1851         if (!session) {
1852                 return -1;
1853         }
1854
1855         lo_arg **argv = lo_message_get_argv(msg);
1856
1857         uint32_t rid = argv[0]->i;
1858
1859
1860         boost::shared_ptr<Stripable> strip = get_strip(rid, get_address(msg));
1861         if (!strip) {
1862                 return -1;
1863         }
1864
1865         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (strip);
1866         if (!r) {
1867                 return -1;
1868         }
1869
1870         boost::shared_ptr<RouteList> route_list = session->get_routes();
1871
1872         lo_message reply = lo_message_new();
1873
1874         for (RouteList::iterator i = route_list->begin(); i != route_list->end(); ++i) {
1875                 boost::shared_ptr<Route> tr = boost::dynamic_pointer_cast<Route> (*i);
1876                 if (!tr) {
1877                         continue;
1878                 }
1879                 int j = 0;
1880
1881                 for (;;) {
1882                         boost::shared_ptr<Processor> p = tr->nth_send(j++);
1883
1884                         if (!p) {
1885                                 break;
1886                         }
1887
1888                         boost::shared_ptr<InternalSend> isend = boost::dynamic_pointer_cast<InternalSend> (p);
1889                         if (isend) {
1890                                 if( isend->target_route()->id() == r->id()){
1891                                         boost::shared_ptr<Amp> a = isend->amp();
1892
1893                                         lo_message_add_int32(reply, get_sid(tr, get_address(msg)));
1894                                         lo_message_add_string(reply, tr->name().c_str());
1895                                         lo_message_add_int32(reply, j);
1896                                         lo_message_add_float(reply, gain_to_slider_position(a->gain_control()->get_value()));
1897                                         lo_message_add_int32(reply, p->active() ? 1 : 0);
1898                                 }
1899                         }
1900                 }
1901         }
1902
1903         // I have used a dedicated message path to identify this reply in async operation. Naming it #reply wont help the client to identify the content.
1904         lo_send_message(get_address (msg), "/strip/receives", reply);
1905         lo_message_free(reply);
1906         return 0;
1907 }
1908
1909 // strip calls
1910 int
1911 OSC::route_mute (int ssid, int yn, lo_message msg)
1912 {
1913         if (!session) return -1;
1914         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
1915
1916         if (s) {
1917                 if (s->mute_control()) {
1918                         s->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1919                         return 0;
1920                 }
1921         }
1922
1923         return route_send_fail ("mute", ssid, 0, get_address (msg));
1924 }
1925
1926 int
1927 OSC::sel_mute (uint32_t yn, lo_message msg)
1928 {
1929         OSCSurface *sur = get_surface(get_address (msg));
1930         boost::shared_ptr<Stripable> s;
1931         if (sur->expand_enable) {
1932                 s = get_strip (sur->expand, get_address (msg));
1933         } else {
1934                 s = _select;
1935         }
1936         if (s) {
1937                 if (s->mute_control()) {
1938                         s->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1939                         return 0;
1940                 }
1941         }
1942         return sel_fail ("mute", 0, get_address (msg));
1943 }
1944
1945 int
1946 OSC::route_solo (int ssid, int yn, lo_message msg)
1947 {
1948         if (!session) return -1;
1949         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
1950
1951         if (s) {
1952                 if (s->solo_control()) {
1953                         s->solo_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1954                         return route_send_fail ("solo", ssid, (float) s->solo_control()->get_value(), get_address (msg));
1955                 }
1956         }
1957
1958         return route_send_fail ("solo", ssid, 0, get_address (msg));
1959 }
1960
1961 int
1962 OSC::route_solo_iso (int ssid, int yn, lo_message msg)
1963 {
1964         if (!session) return -1;
1965         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
1966
1967         if (s) {
1968                 if (s->solo_isolate_control()) {
1969                         s->solo_isolate_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1970                         return 0;
1971                 }
1972         }
1973
1974         return route_send_fail ("solo_iso", ssid, 0, get_address (msg));
1975 }
1976
1977 int
1978 OSC::route_solo_safe (int ssid, int yn, lo_message msg)
1979 {
1980         if (!session) return -1;
1981         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
1982
1983         if (s) {
1984                 if (s->solo_safe_control()) {
1985                         s->solo_safe_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1986                         return 0;
1987                 }
1988         }
1989
1990         return route_send_fail ("solo_safe", ssid, 0, get_address (msg));
1991 }
1992
1993 int
1994 OSC::sel_solo (uint32_t yn, lo_message msg)
1995 {
1996         OSCSurface *sur = get_surface(get_address (msg));
1997         boost::shared_ptr<Stripable> s;
1998         if (sur->expand_enable) {
1999                 s = get_strip (sur->expand, get_address (msg));
2000         } else {
2001                 s = _select;
2002         }
2003         if (s) {
2004                 if (s->solo_control()) {
2005                         s->solo_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2006                         return sel_fail ("solo", (float) s->solo_control()->get_value(), get_address (msg));
2007                 }
2008         }
2009         return sel_fail ("solo", 0, get_address (msg));
2010 }
2011
2012 int
2013 OSC::sel_solo_iso (uint32_t yn, lo_message msg)
2014 {
2015         OSCSurface *sur = get_surface(get_address (msg));
2016         boost::shared_ptr<Stripable> s;
2017         if (sur->expand_enable) {
2018                 s = get_strip (sur->expand, get_address (msg));
2019         } else {
2020                 s = _select;
2021         }
2022         if (s) {
2023                 if (s->solo_isolate_control()) {
2024                         s->solo_isolate_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2025                         return 0;
2026                 }
2027         }
2028         return sel_fail ("solo_iso", 0, get_address (msg));
2029 }
2030
2031 int
2032 OSC::sel_solo_safe (uint32_t yn, lo_message msg)
2033 {
2034         OSCSurface *sur = get_surface(get_address (msg));
2035         boost::shared_ptr<Stripable> s;
2036         if (sur->expand_enable) {
2037                 s = get_strip (sur->expand, get_address (msg));
2038         } else {
2039                 s = _select;
2040         }
2041         if (s) {
2042                 if (s->solo_safe_control()) {
2043                         s->solo_safe_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2044                         return 0;
2045                 }
2046         }
2047         return sel_fail ("solo_safe", 0, get_address (msg));
2048 }
2049
2050 int
2051 OSC::sel_recenable (uint32_t yn, lo_message msg)
2052 {
2053         OSCSurface *sur = get_surface(get_address (msg));
2054         boost::shared_ptr<Stripable> s;
2055         if (sur->expand_enable) {
2056                 s = get_strip (sur->expand, get_address (msg));
2057         } else {
2058                 s = _select;
2059         }
2060         if (s) {
2061                 if (s->rec_enable_control()) {
2062                         s->rec_enable_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2063                         if (s->rec_enable_control()->get_value()) {
2064                                 return 0;
2065                         }
2066                 }
2067         }
2068         return sel_fail ("recenable", 0, get_address (msg));
2069 }
2070
2071 int
2072 OSC::route_recenable (int ssid, int yn, lo_message msg)
2073 {
2074         if (!session) return -1;
2075         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2076
2077         if (s) {
2078                 if (s->rec_enable_control()) {
2079                         s->rec_enable_control()->set_value (yn, PBD::Controllable::UseGroup);
2080                         if (s->rec_enable_control()->get_value()) {
2081                                 return 0;
2082                         }
2083                 }
2084         }
2085         return route_send_fail ("recenable", ssid, 0, get_address (msg));
2086 }
2087
2088 int
2089 OSC::route_rename(int ssid, char *newname, lo_message msg) {
2090     if (!session) {
2091         return -1;
2092     }
2093
2094     boost::shared_ptr<Stripable> s = get_strip(ssid, get_address(msg));
2095
2096     if (s) {
2097         s->set_name(std::string(newname));
2098     }
2099
2100     return 0;
2101 }
2102
2103 int
2104 OSC::sel_recsafe (uint32_t yn, lo_message msg)
2105 {
2106         OSCSurface *sur = get_surface(get_address (msg));
2107         boost::shared_ptr<Stripable> s;
2108         if (sur->expand_enable) {
2109                 s = get_strip (sur->expand, get_address (msg));
2110         } else {
2111                 s = _select;
2112         }
2113         if (s) {
2114                 if (s->rec_safe_control()) {
2115                         s->rec_safe_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2116                         if (s->rec_safe_control()->get_value()) {
2117                                 return 0;
2118                         }
2119                 }
2120         }
2121         return sel_fail ("record_safe", 0, get_address (msg));
2122 }
2123
2124 int
2125 OSC::route_recsafe (int ssid, int yn, lo_message msg)
2126 {
2127         if (!session) return -1;
2128         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2129         if (s) {
2130                 if (s->rec_safe_control()) {
2131                         s->rec_safe_control()->set_value (yn, PBD::Controllable::UseGroup);
2132                         if (s->rec_safe_control()->get_value()) {
2133                                 return 0;
2134                         }
2135                 }
2136         }
2137         return route_send_fail ("record_safe", ssid, 0,get_address (msg));
2138 }
2139
2140 int
2141 OSC::route_monitor_input (int ssid, int yn, lo_message msg)
2142 {
2143         if (!session) return -1;
2144         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2145
2146         if (s) {
2147                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
2148                 if (track) {
2149                         if (track->monitoring_control()) {
2150                                 track->monitoring_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2151                                 return 0;
2152                         }
2153                 }
2154         }
2155
2156         return route_send_fail ("monitor_input", ssid, 0, get_address (msg));
2157 }
2158
2159 int
2160 OSC::sel_monitor_input (uint32_t yn, lo_message msg)
2161 {
2162         OSCSurface *sur = get_surface(get_address (msg));
2163         boost::shared_ptr<Stripable> s;
2164         if (sur->expand_enable) {
2165                 s = get_strip (sur->expand, get_address (msg));
2166         } else {
2167                 s = _select;
2168         }
2169         if (s) {
2170                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
2171                 if (track) {
2172                         if (track->monitoring_control()) {
2173                                 track->monitoring_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2174                                 return 0;
2175                         }
2176                 }
2177         }
2178         return sel_fail ("monitor_input", 0, get_address (msg));
2179 }
2180
2181 int
2182 OSC::route_monitor_disk (int ssid, int yn, lo_message msg)
2183 {
2184         if (!session) return -1;
2185         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2186
2187         if (s) {
2188                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
2189                 if (track) {
2190                         if (track->monitoring_control()) {
2191                                 track->monitoring_control()->set_value (yn ? 2.0 : 0.0, PBD::Controllable::NoGroup);
2192                                 return 0;
2193                         }
2194                 }
2195         }
2196
2197         return route_send_fail ("monitor_disk", ssid, 0, get_address (msg));
2198 }
2199
2200 int
2201 OSC::sel_monitor_disk (uint32_t yn, lo_message msg)
2202 {
2203         OSCSurface *sur = get_surface(get_address (msg));
2204         boost::shared_ptr<Stripable> s;
2205         if (sur->expand_enable) {
2206                 s = get_strip (sur->expand, get_address (msg));
2207         } else {
2208                 s = _select;
2209         }
2210         if (s) {
2211                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
2212                 if (track) {
2213                         if (track->monitoring_control()) {
2214                                 track->monitoring_control()->set_value (yn ? 2.0 : 0.0, PBD::Controllable::NoGroup);
2215                                 return 0;
2216                         }
2217                 }
2218         }
2219         return sel_fail ("monitor_disk", 0, get_address (msg));
2220 }
2221
2222
2223 int
2224 OSC::strip_phase (int ssid, int yn, lo_message msg)
2225 {
2226         if (!session) return -1;
2227         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2228
2229         if (s) {
2230                 if (s->phase_control()) {
2231                         s->phase_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2232                         return 0;
2233                 }
2234         }
2235
2236         return route_send_fail ("polarity", ssid, 0, get_address (msg));
2237 }
2238
2239 int
2240 OSC::sel_phase (uint32_t yn, lo_message msg)
2241 {
2242         OSCSurface *sur = get_surface(get_address (msg));
2243         boost::shared_ptr<Stripable> s;
2244         if (sur->expand_enable) {
2245                 s = get_strip (sur->expand, get_address (msg));
2246         } else {
2247                 s = _select;
2248         }
2249         if (s) {
2250                 if (s->phase_control()) {
2251                         s->phase_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
2252                         return 0;
2253                 }
2254         }
2255         return sel_fail ("polarity", 0, get_address (msg));
2256 }
2257
2258 int
2259 OSC::strip_expand (int ssid, int yn, lo_message msg)
2260 {
2261         OSCSurface *sur = get_surface(get_address (msg));
2262         sur->expand_enable = (bool) yn;
2263         sur->expand = ssid;
2264         boost::shared_ptr<Stripable> s;
2265         if (yn) {
2266                 s = get_strip (ssid, get_address (msg));
2267         } else {
2268                 s = ControlProtocol::first_selected_stripable();
2269         }
2270
2271         return _strip_select (s, get_address (msg));
2272 }
2273
2274 int
2275 OSC::_strip_select (boost::shared_ptr<Stripable> s, lo_address addr)
2276 {
2277         if (!session) {
2278                 return -1;
2279         }
2280         OSCSurface *sur = get_surface(addr);
2281         if (sur->sel_obs) {
2282                 delete sur->sel_obs;
2283                 sur->sel_obs = 0;
2284         }
2285         bool feedback_on = sur->feedback.to_ulong();
2286         if (s && feedback_on) {
2287                 OSCSelectObserver* sel_fb = new OSCSelectObserver (s, addr, sur->gainmode, sur->feedback);
2288                 s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
2289                 sur->sel_obs = sel_fb;
2290         } else if (sur->expand_enable) {
2291                 sur->expand = 0;
2292                 sur->expand_enable = false;
2293                 if (_select && feedback_on) {
2294                         OSCSelectObserver* sel_fb = new OSCSelectObserver (_select, addr, sur->gainmode, sur->feedback);
2295                         _select->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
2296                         sur->sel_obs = sel_fb;
2297                 }
2298         } else if (feedback_on) {
2299                 route_send_fail ("select", sur->expand, 0 , addr);
2300         }
2301         if (!feedback_on) {
2302                 return 0;
2303         }
2304         //update buttons on surface
2305         int b_s = sur->bank_size;
2306         if (!b_s) { // bank size 0 means we need to know how many strips there are.
2307                 b_s = sur->nstrips;
2308         }
2309         for (int i = 1;  i <= b_s; i++) {
2310                 string path = "expand";
2311
2312                 if ((i == (int) sur->expand) && sur->expand_enable) {
2313                         lo_message reply = lo_message_new ();
2314                         if (sur->feedback[2]) {
2315                                 ostringstream os;
2316                                 os << "/strip/" << path << "/" << i;
2317                                 path = os.str();
2318                         } else {
2319                                 ostringstream os;
2320                                 os << "/strip/" << path;
2321                                 path = os.str();
2322                                 lo_message_add_int32 (reply, i);
2323                         }
2324                         lo_message_add_float (reply, (float) 1);
2325
2326                         lo_send_message (addr, path.c_str(), reply);
2327                         lo_message_free (reply);
2328                         reply = lo_message_new ();
2329                         lo_message_add_float (reply, 1.0);
2330                         lo_send_message (addr, "/select/expand", reply);
2331                         lo_message_free (reply);
2332
2333                 } else {
2334                         lo_message reply = lo_message_new ();
2335                         lo_message_add_int32 (reply, i);
2336                         lo_message_add_float (reply, 0.0);
2337                         lo_send_message (addr, "/strip/expand", reply);
2338                         lo_message_free (reply);
2339                 }
2340         }
2341         if (!sur->expand_enable) {
2342                 lo_message reply = lo_message_new ();
2343                 lo_message_add_float (reply, 0.0);
2344                 lo_send_message (addr, "/select/expand", reply);
2345                 lo_message_free (reply);
2346         }
2347
2348         return 0;
2349 }
2350
2351 int
2352 OSC::strip_gui_select (int ssid, int yn, lo_message msg)
2353 {
2354         //ignore button release
2355         if (!yn) return 0;
2356
2357         if (!session) {
2358                 return -1;
2359         }
2360         OSCSurface *sur = get_surface(get_address (msg));
2361         sur->expand_enable = false;
2362         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2363         if (s) {
2364                 SetStripableSelection (s);
2365         } else {
2366                 if ((int) (sur->feedback.to_ulong())) {
2367                         route_send_fail ("select", ssid, 0, get_address (msg));
2368                 }
2369         }
2370
2371         return 0;
2372 }
2373
2374 int
2375 OSC::sel_expand (uint32_t state, lo_message msg)
2376 {
2377         OSCSurface *sur = get_surface(get_address (msg));
2378         boost::shared_ptr<Stripable> s;
2379         sur->expand_enable = (bool) state;
2380         if (state && sur->expand) {
2381                 s = get_strip (sur->expand, get_address (msg));
2382         } else {
2383                 s = ControlProtocol::first_selected_stripable();
2384         }
2385
2386         return _strip_select (s, get_address (msg));
2387 }
2388
2389 int
2390 OSC::route_set_gain_abs (int ssid, float level, lo_message msg)
2391 {
2392         if (!session) return -1;
2393         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2394
2395         if (s) {
2396                 if (s->gain_control()) {
2397                         s->gain_control()->set_value (level, PBD::Controllable::NoGroup);
2398                 } else {
2399                         return 1;
2400                 }
2401         } else {
2402                 return 1;
2403         }
2404
2405         return 0;
2406 }
2407
2408 int
2409 OSC::route_set_gain_dB (int ssid, float dB, lo_message msg)
2410 {
2411         if (!session) {
2412                 route_send_fail ("gain", ssid, -193, get_address (msg));
2413                 return -1;
2414         }
2415         int ret;
2416         if (dB < -192) {
2417                 ret = route_set_gain_abs (ssid, 0.0, msg);
2418         } else {
2419                 ret = route_set_gain_abs (ssid, dB_to_coefficient (dB), msg);
2420         }
2421         if (ret != 0) {
2422                 return route_send_fail ("gain", ssid, -193, get_address (msg));
2423         }
2424         return 0;
2425 }
2426
2427 int
2428 OSC::sel_gain (float val, lo_message msg)
2429 {
2430         OSCSurface *sur = get_surface(get_address (msg));
2431         boost::shared_ptr<Stripable> s;
2432         if (sur->expand_enable) {
2433                 s = get_strip (sur->expand, get_address (msg));
2434         } else {
2435                 s = _select;
2436         }
2437         if (s) {
2438                 float abs;
2439                 if (val < -192) {
2440                         abs = 0;
2441                 } else {
2442                         abs = dB_to_coefficient (val);
2443                 }
2444                 if (s->gain_control()) {
2445                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
2446                         return 0;
2447                 }
2448         }
2449         return sel_fail ("gain", -193, get_address (msg));
2450 }
2451
2452 int
2453 OSC::route_set_gain_fader (int ssid, float pos, lo_message msg)
2454 {
2455         if (!session) {
2456                 route_send_fail ("fader", ssid, 0, get_address (msg));
2457                 return -1;
2458         }
2459         int ret;
2460         ret = route_set_gain_abs (ssid, slider_position_to_gain_with_max (pos, 2.0), msg);
2461         if (ret != 0) {
2462                 return route_send_fail ("fader", ssid, 0, get_address (msg));
2463         }
2464         return 0;
2465 }
2466
2467 int
2468 OSC::sel_fader (float val, lo_message msg)
2469 {
2470         OSCSurface *sur = get_surface(get_address (msg));
2471         boost::shared_ptr<Stripable> s;
2472         if (sur->expand_enable) {
2473                 s = get_strip (sur->expand, get_address (msg));
2474         } else {
2475                 s = _select;
2476         }
2477         if (s) {
2478                 float abs;
2479                 abs = slider_position_to_gain_with_max (val, 2.0);
2480                 if (s->gain_control()) {
2481                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
2482                         return 0;
2483                 }
2484         }
2485         return sel_fail ("fader", 0, get_address (msg));
2486 }
2487
2488 int
2489 OSC::route_set_trim_abs (int ssid, float level, lo_message msg)
2490 {
2491         if (!session) return -1;
2492         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2493
2494         if (s) {
2495                 if (s->trim_control()) {
2496                         s->trim_control()->set_value (level, PBD::Controllable::NoGroup);
2497                         return 0;
2498                 }
2499
2500         }
2501
2502         return -1;
2503 }
2504
2505 int
2506 OSC::route_set_trim_dB (int ssid, float dB, lo_message msg)
2507 {
2508         int ret;
2509         ret = route_set_trim_abs(ssid, dB_to_coefficient (dB), msg);
2510         if (ret != 0) {
2511                 return route_send_fail ("trimdB", ssid, 0, get_address (msg));
2512         }
2513
2514 return 0;
2515 }
2516
2517 int
2518 OSC::sel_trim (float val, lo_message msg)
2519 {
2520         OSCSurface *sur = get_surface(get_address (msg));
2521         boost::shared_ptr<Stripable> s;
2522         if (sur->expand_enable) {
2523                 s = get_strip (sur->expand, get_address (msg));
2524         } else {
2525                 s = _select;
2526         }
2527         if (s) {
2528                 if (s->trim_control()) {
2529                         s->trim_control()->set_value (dB_to_coefficient (val), PBD::Controllable::NoGroup);
2530                         return 0;
2531                 }
2532         }
2533         return sel_fail ("trimdB", 0, get_address (msg));
2534 }
2535
2536 int
2537 OSC::sel_pan_position (float val, lo_message msg)
2538 {
2539         OSCSurface *sur = get_surface(get_address (msg));
2540         boost::shared_ptr<Stripable> s;
2541         if (sur->expand_enable) {
2542                 s = get_strip (sur->expand, get_address (msg));
2543         } else {
2544                 s = _select;
2545         }
2546         if (s) {
2547                 if(s->pan_azimuth_control()) {
2548                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
2549                         return sel_fail ("pan_stereo_position", s->pan_azimuth_control()->internal_to_interface (s->pan_azimuth_control()->get_value ()), get_address (msg));
2550                         return 0;
2551                 }
2552         }
2553         return sel_fail ("pan_stereo_position", 0.5, get_address (msg));
2554 }
2555
2556 int
2557 OSC::sel_pan_width (float val, lo_message msg)
2558 {
2559         OSCSurface *sur = get_surface(get_address (msg));
2560         boost::shared_ptr<Stripable> s;
2561         if (sur->expand_enable) {
2562                 s = get_strip (sur->expand, get_address (msg));
2563         } else {
2564                 s = _select;
2565         }
2566         if (s) {
2567                 if (s->pan_width_control()) {
2568                         s->pan_width_control()->set_value (s->pan_width_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
2569                         return 0;
2570                 }
2571         }
2572         return sel_fail ("pan_stereo_width", 1, get_address (msg));
2573 }
2574
2575 int
2576 OSC::route_set_pan_stereo_position (int ssid, float pos, lo_message msg)
2577 {
2578         if (!session) return -1;
2579         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2580
2581         if (s) {
2582                 if(s->pan_azimuth_control()) {
2583                         s->pan_azimuth_control()->set_value (s->pan_azimuth_control()->interface_to_internal (pos), PBD::Controllable::NoGroup);
2584                         return route_send_fail ("pan_stereo_position", ssid, s->pan_azimuth_control()->internal_to_interface (s->pan_azimuth_control()->get_value ()), get_address (msg));
2585                 }
2586         }
2587
2588         return route_send_fail ("pan_stereo_position", ssid, 0.5, get_address (msg));
2589 }
2590
2591 int
2592 OSC::route_set_pan_stereo_width (int ssid, float pos, lo_message msg)
2593 {
2594         if (!session) return -1;
2595         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2596
2597         if (s) {
2598                 if (s->pan_width_control()) {
2599                         s->pan_width_control()->set_value (pos, PBD::Controllable::NoGroup);
2600                         return 0;
2601                 }
2602         }
2603
2604         return route_send_fail ("pan_stereo_width", ssid, 1, get_address (msg));
2605 }
2606
2607 int
2608 OSC::route_set_send_gain_dB (int ssid, int id, float val, lo_message msg)
2609 {
2610         if (!session) {
2611                 return -1;
2612         }
2613         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2614         float abs;
2615         if (s) {
2616                 if (id > 0) {
2617                         --id;
2618                 }
2619 #ifdef MIXBUS
2620                 abs = val;
2621 #else
2622                 if (val < -192) {
2623                         abs = 0;
2624                 } else {
2625                         abs = dB_to_coefficient (val);
2626                 }
2627 #endif
2628                 if (s->send_level_controllable (id)) {
2629                         s->send_level_controllable (id)->set_value (abs, PBD::Controllable::NoGroup);
2630                         return 0;
2631                 }
2632         }
2633         return 0;
2634 }
2635
2636 int
2637 OSC::route_set_send_fader (int ssid, int id, float val, lo_message msg)
2638 {
2639         if (!session) {
2640                 return -1;
2641         }
2642         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2643         float abs;
2644         if (s) {
2645
2646                 if (id > 0) {
2647                         --id;
2648                 }
2649
2650                 if (s->send_level_controllable (id)) {
2651 #ifdef MIXBUS
2652                         abs = s->send_level_controllable(id)->interface_to_internal (val);
2653 #else
2654                         abs = slider_position_to_gain_with_max (val, 2.0);
2655 #endif
2656                         s->send_level_controllable (id)->set_value (abs, PBD::Controllable::NoGroup);
2657                         return 0;
2658                 }
2659         }
2660         return 0;
2661 }
2662
2663 int
2664 OSC::sel_sendgain (int id, float val, lo_message msg)
2665 {
2666         OSCSurface *sur = get_surface(get_address (msg));
2667         boost::shared_ptr<Stripable> s;
2668         if (sur->expand_enable) {
2669                 s = get_strip (sur->expand, get_address (msg));
2670         } else {
2671                 s = _select;
2672         }
2673         float abs;
2674         if (s) {
2675                 if (id > 0) {
2676                         --id;
2677                 }
2678 #ifdef MIXBUS
2679                 abs = val;
2680 #else
2681                 if (val < -192) {
2682                         abs = 0;
2683                 } else {
2684                         abs = dB_to_coefficient (val);
2685                 }
2686 #endif
2687                 if (s->send_level_controllable (id)) {
2688                         s->send_level_controllable (id)->set_value (abs, PBD::Controllable::NoGroup);
2689                         return 0;
2690                 }
2691         }
2692         return sel_send_fail ("send_gain", id + 1, -193, get_address (msg));
2693 }
2694
2695 int
2696 OSC::sel_sendfader (int id, float val, lo_message msg)
2697 {
2698         OSCSurface *sur = get_surface(get_address (msg));
2699         boost::shared_ptr<Stripable> s;
2700         if (sur->expand_enable) {
2701                 s = get_strip (sur->expand, get_address (msg));
2702         } else {
2703                 s = _select;
2704         }
2705         float abs;
2706         if (s) {
2707
2708                 if (id > 0) {
2709                         --id;
2710                 }
2711
2712                 if (s->send_level_controllable (id)) {
2713 #ifdef MIXBUS
2714                         abs = s->send_level_controllable(id)->interface_to_internal (val);
2715 #else
2716                         abs = slider_position_to_gain_with_max (val, 2.0);
2717 #endif
2718                         s->send_level_controllable (id)->set_value (abs, PBD::Controllable::NoGroup);
2719                         return 0;
2720                 }
2721         }
2722         return sel_send_fail ("send_fader", id, 0, get_address (msg));
2723 }
2724
2725 int
2726 OSC::route_set_send_enable (int ssid, int sid, float val, lo_message msg)
2727 {
2728         if (!session) {
2729                 return -1;
2730         }
2731         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2732
2733         if (s) {
2734
2735                 /* revert to zero-based counting */
2736
2737                 if (sid > 0) {
2738                         --sid;
2739                 }
2740
2741                 if (s->send_enable_controllable (sid)) {
2742                         s->send_enable_controllable (sid)->set_value (val, PBD::Controllable::NoGroup);
2743                         return 0;
2744                 }
2745
2746                 if (s->send_level_controllable (sid)) {
2747                         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
2748                         if (!r) {
2749                                 return 0;
2750                         }
2751                         boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(sid));
2752                         if (snd) {
2753                                 if (val) {
2754                                         snd->activate();
2755                                 } else {
2756                                         snd->deactivate();
2757                                 }
2758                         }
2759                         return 0;
2760                 }
2761
2762         }
2763
2764         return -1;
2765 }
2766
2767 int
2768 OSC::sel_sendenable (int id, float val, lo_message msg)
2769 {
2770         OSCSurface *sur = get_surface(get_address (msg));
2771         boost::shared_ptr<Stripable> s;
2772         if (sur->expand_enable) {
2773                 s = get_strip (sur->expand, get_address (msg));
2774         } else {
2775                 s = _select;
2776         }
2777         if (s) {
2778                 if (id > 0) {
2779                         --id;
2780                 }
2781                 if (s->send_enable_controllable (id)) {
2782                         s->send_enable_controllable (id)->set_value (val, PBD::Controllable::NoGroup);
2783                         return 0;
2784                 }
2785                 if (s->send_level_controllable (id)) {
2786                         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
2787                         if (!r) {
2788                                 // should never get here
2789                                 return sel_send_fail ("send_enable", id + 1, 0, get_address (msg));
2790                         }
2791                         boost::shared_ptr<Send> snd = boost::dynamic_pointer_cast<Send> (r->nth_send(id));
2792                         if (snd) {
2793                                 if (val) {
2794                                         snd->activate();
2795                                 } else {
2796                                         snd->deactivate();
2797                                 }
2798                         }
2799                         return 0;
2800                 }
2801         }
2802         return sel_send_fail ("send_enable", id + 1, 0, get_address (msg));
2803 }
2804
2805 int
2806 OSC::route_plugin_list (int ssid, lo_message msg) {
2807         if (!session) {
2808                 return -1;
2809         }
2810
2811         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
2812
2813         if (!r) {
2814                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
2815                 return -1;
2816         }
2817         int piid = 0;
2818
2819         lo_message reply = lo_message_new ();
2820         lo_message_add_int32 (reply, ssid);
2821
2822
2823         for (;;) {
2824                 boost::shared_ptr<Processor> redi = r->nth_plugin(piid);
2825                 if ( !redi ) {
2826                         break;
2827                 }
2828
2829                 boost::shared_ptr<PluginInsert> pi;
2830
2831                 if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
2832                         PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
2833                         continue;
2834                 }
2835                 lo_message_add_int32 (reply, piid + 1);
2836
2837                 boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
2838                 lo_message_add_string (reply, pip->name());
2839
2840                 piid++;
2841         }
2842
2843         lo_send_message (get_address (msg), "/strip/plugin/list", reply);
2844         lo_message_free (reply);
2845         return 0;
2846 }
2847
2848 int
2849 OSC::route_plugin_descriptor (int ssid, int piid, lo_message msg) {
2850         if (!session) {
2851                 return -1;
2852         }
2853
2854         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
2855
2856         if (!r) {
2857                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
2858                 return -1;
2859         }
2860
2861         boost::shared_ptr<Processor> redi = r->nth_plugin(piid - 1);
2862
2863         if (!redi) {
2864                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
2865                 return -1;
2866         }
2867
2868         boost::shared_ptr<PluginInsert> pi;
2869
2870         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
2871                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
2872                 return -1;
2873         }
2874
2875         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
2876         bool ok = false;
2877
2878         lo_message reply = lo_message_new();
2879         lo_message_add_int32 (reply, ssid);
2880         lo_message_add_int32 (reply, piid);
2881         lo_message_add_string (reply, pip->name());
2882         for ( uint32_t ppi = 0; ppi < pip->parameter_count(); ppi++) {
2883
2884                 uint32_t controlid = pip->nth_parameter(ppi, ok);
2885                 if (!ok) {
2886                         continue;
2887                 }
2888                 if ( pip->parameter_is_input(controlid) || pip->parameter_is_control(controlid) ) {
2889                         boost::shared_ptr<AutomationControl> c = pi->automation_control(Evoral::Parameter(PluginAutomation, 0, controlid));
2890
2891                                 lo_message_add_int32 (reply, ppi + 1);
2892                                 ParameterDescriptor pd;
2893                                 pi->plugin()->get_parameter_descriptor(controlid, pd);
2894                                 lo_message_add_string (reply, pd.label.c_str());
2895
2896                                 // I've combined those binary descriptor parts in a bit-field to reduce lilo message elements
2897                                 int flags = 0;
2898                                 flags |= pd.enumeration ? 1 : 0;
2899                                 flags |= pd.integer_step ? 2 : 0;
2900                                 flags |= pd.logarithmic ? 4 : 0;
2901                                 flags |= pd.max_unbound ? 8 : 0;
2902                                 flags |= pd.min_unbound ? 16 : 0;
2903                                 flags |= pd.sr_dependent ? 32 : 0;
2904                                 flags |= pd.toggled ? 64 : 0;
2905                                 flags |= c != NULL ? 128 : 0; // bit 7 indicates in input control
2906                                 lo_message_add_int32 (reply, flags);
2907
2908                                 lo_message_add_int32 (reply, pd.datatype);
2909                                 lo_message_add_float (reply, pd.lower);
2910                                 lo_message_add_float (reply, pd.upper);
2911                                 lo_message_add_string (reply, pd.print_fmt.c_str());
2912                                 if ( pd.scale_points ) {
2913                                         lo_message_add_int32 (reply, pd.scale_points->size());
2914                                         for ( ARDOUR::ScalePoints::const_iterator i = pd.scale_points->begin(); i != pd.scale_points->end(); ++i) {
2915                                                 lo_message_add_int32 (reply, i->second);
2916                                                 lo_message_add_string (reply, ((std::string)i->first).c_str());
2917                                         }
2918                                 }
2919                                 else {
2920                                         lo_message_add_int32 (reply, 0);
2921                                 }
2922                                 if ( c ) {
2923                                         lo_message_add_double (reply, c->get_value());
2924                                 }
2925                                 else {
2926                                         lo_message_add_double (reply, 0);
2927                         }
2928                 }
2929         }
2930
2931         lo_send_message (get_address (msg), "/strip/plugin/descriptor", reply);
2932         lo_message_free (reply);
2933
2934         return 0;
2935 }
2936
2937 int
2938 OSC::route_plugin_reset (int ssid, int piid, lo_message msg) {
2939         if (!session) {
2940                 return -1;
2941         }
2942
2943         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route>(get_strip (ssid, get_address (msg)));
2944
2945         if (!r) {
2946                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
2947                 return -1;
2948         }
2949
2950         boost::shared_ptr<Processor> redi = r->nth_plugin(piid - 1);
2951
2952         if (!redi) {
2953                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
2954                 return -1;
2955         }
2956
2957         boost::shared_ptr<PluginInsert> pi;
2958
2959         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
2960                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
2961                 return -1;
2962         }
2963
2964         pi->reset_parameters_to_default ();
2965
2966         return 0;
2967 }
2968
2969 int
2970 OSC::route_plugin_parameter (int ssid, int piid, int par, float val, lo_message msg)
2971 {
2972         if (!session)
2973                 return -1;
2974         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
2975
2976         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
2977
2978         if (!r) {
2979                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
2980                 return -1;
2981         }
2982
2983         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
2984
2985         if (!redi) {
2986                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
2987                 return -1;
2988         }
2989
2990         boost::shared_ptr<PluginInsert> pi;
2991
2992         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
2993                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
2994                 return -1;
2995         }
2996
2997         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
2998         bool ok=false;
2999
3000         uint32_t controlid = pip->nth_parameter (par - 1,ok);
3001
3002         if (!ok) {
3003                 PBD::error << "OSC: Cannot find parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "'" << endmsg;
3004                 return -1;
3005         }
3006
3007         if (!pip->parameter_is_input(controlid)) {
3008                 PBD::error << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "' is not a control input" << endmsg;
3009                 return -1;
3010         }
3011
3012         ParameterDescriptor pd;
3013         pi->plugin()->get_parameter_descriptor (controlid,pd);
3014
3015         if (val >= pd.lower && val <= pd.upper) {
3016
3017                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
3018                 // cerr << "parameter:" << redi->describe_parameter(controlid) << " val:" << val << "\n";
3019                 c->set_value (val, PBD::Controllable::NoGroup);
3020         } else {
3021                 PBD::warning << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << ssid << "' is out of range" << endmsg;
3022                 PBD::info << "OSC: Valid range min=" << pd.lower << " max=" << pd.upper << endmsg;
3023         }
3024
3025         return 0;
3026 }
3027
3028 //prints to cerr only
3029 int
3030 OSC::route_plugin_parameter_print (int ssid, int piid, int par, lo_message msg)
3031 {
3032         if (!session) {
3033                 return -1;
3034         }
3035         boost::shared_ptr<Stripable> s = get_strip (ssid, get_address (msg));
3036
3037         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
3038
3039         if (!r) {
3040                 return -1;
3041         }
3042
3043         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
3044
3045         if (!redi) {
3046                 return -1;
3047         }
3048
3049         boost::shared_ptr<PluginInsert> pi;
3050
3051         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
3052                 return -1;
3053         }
3054
3055         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
3056         bool ok=false;
3057
3058         uint32_t controlid = pip->nth_parameter (par - 1,ok);
3059
3060         if (!ok) {
3061                 return -1;
3062         }
3063
3064         ParameterDescriptor pd;
3065
3066         if (pi->plugin()->get_parameter_descriptor (controlid, pd) == 0) {
3067                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
3068
3069                 cerr << "parameter:     " << pd.label  << "\n";
3070                 if (c) {
3071                         cerr << "current value: " << c->get_value () << "\n";
3072                 } else {
3073                         cerr << "current value not available, control does not exist\n";
3074                 }
3075                 cerr << "lower value:   " << pd.lower << "\n";
3076                 cerr << "upper value:   " << pd.upper << "\n";
3077         }
3078
3079         return 0;
3080 }
3081
3082 int
3083 OSC::route_plugin_activate (int ssid, int piid, lo_message msg)
3084 {
3085         if (!session)
3086                 return -1;
3087         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
3088
3089         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
3090
3091         if (!r) {
3092                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
3093                 return -1;
3094         }
3095
3096         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
3097
3098         if (!redi) {
3099                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
3100                 return -1;
3101         }
3102
3103         boost::shared_ptr<PluginInsert> pi;
3104
3105         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
3106                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
3107                 return -1;
3108         }
3109
3110         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
3111         pi->activate();
3112
3113         return 0;
3114 }
3115
3116 int
3117 OSC::route_plugin_deactivate (int ssid, int piid, lo_message msg)
3118 {
3119         if (!session)
3120                 return -1;
3121         boost::shared_ptr<Stripable> s = get_strip (ssid, lo_message_get_source (msg));
3122
3123         boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
3124
3125         if (!r) {
3126                 PBD::error << "OSC: Invalid Remote Control ID '" << ssid << "'" << endmsg;
3127                 return -1;
3128         }
3129
3130         boost::shared_ptr<Processor> redi=r->nth_plugin (piid - 1);
3131
3132         if (!redi) {
3133                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << ssid << "'" << endmsg;
3134                 return -1;
3135         }
3136
3137         boost::shared_ptr<PluginInsert> pi;
3138
3139         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
3140                 PBD::error << "OSC: given processor # " << piid << " on RID '" << ssid << "' is not a Plugin." << endmsg;
3141                 return -1;
3142         }
3143
3144         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
3145         pi->deactivate();
3146
3147         return 0;
3148 }
3149
3150 // select
3151
3152 int
3153 OSC::sel_pan_elevation (float val, lo_message msg)
3154 {
3155         OSCSurface *sur = get_surface(get_address (msg));
3156         boost::shared_ptr<Stripable> s;
3157         if (sur->expand_enable) {
3158                 s = get_strip (sur->expand, get_address (msg));
3159         } else {
3160                 s = _select;
3161         }
3162         if (s) {
3163                 if (s->pan_elevation_control()) {
3164                         s->pan_elevation_control()->set_value (s->pan_elevation_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
3165                         return 0;
3166                 }
3167         }
3168         return sel_fail ("pan_elevation_position", 0, get_address (msg));
3169 }
3170
3171 int
3172 OSC::sel_pan_frontback (float val, lo_message msg)
3173 {
3174         OSCSurface *sur = get_surface(get_address (msg));
3175         boost::shared_ptr<Stripable> s;
3176         if (sur->expand_enable) {
3177                 s = get_strip (sur->expand, get_address (msg));
3178         } else {
3179                 s = _select;
3180         }
3181         if (s) {
3182                 if (s->pan_frontback_control()) {
3183                         s->pan_frontback_control()->set_value (s->pan_frontback_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
3184                         return 0;
3185                 }
3186         }
3187         return sel_fail ("pan_frontback_position", 0.5, get_address (msg));
3188 }
3189
3190 int
3191 OSC::sel_pan_lfe (float val, lo_message msg)
3192 {
3193         OSCSurface *sur = get_surface(get_address (msg));
3194         boost::shared_ptr<Stripable> s;
3195         if (sur->expand_enable) {
3196                 s = get_strip (sur->expand, get_address (msg));
3197         } else {
3198                 s = _select;
3199         }
3200         if (s) {
3201                 if (s->pan_lfe_control()) {
3202                         s->pan_lfe_control()->set_value (s->pan_lfe_control()->interface_to_internal (val), PBD::Controllable::NoGroup);
3203                         return 0;
3204                 }
3205         }
3206         return sel_fail ("pan_lfe_control", 0, get_address (msg));
3207 }
3208
3209 // compressor control
3210 int
3211 OSC::sel_comp_enable (float val, lo_message msg)
3212 {
3213         OSCSurface *sur = get_surface(get_address (msg));
3214         boost::shared_ptr<Stripable> s;
3215         if (sur->expand_enable) {
3216                 s = get_strip (sur->expand, get_address (msg));
3217         } else {
3218                 s = _select;
3219         }
3220         if (s) {
3221                 if (s->comp_enable_controllable()) {
3222                         s->comp_enable_controllable()->set_value (s->comp_enable_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
3223                         return 0;
3224                 }
3225         }
3226         return sel_fail ("comp_enable", 0, get_address (msg));
3227 }
3228
3229 int
3230 OSC::sel_comp_threshold (float val, lo_message msg)
3231 {
3232         OSCSurface *sur = get_surface(get_address (msg));
3233         boost::shared_ptr<Stripable> s;
3234         if (sur->expand_enable) {
3235                 s = get_strip (sur->expand, get_address (msg));
3236         } else {
3237                 s = _select;
3238         }
3239         if (s) {
3240                 if (s->comp_threshold_controllable()) {
3241                         s->comp_threshold_controllable()->set_value (s->comp_threshold_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
3242                         return 0;
3243                 }
3244         }
3245         return sel_fail ("comp_threshold", 0, get_address (msg));
3246 }
3247
3248 int
3249 OSC::sel_comp_speed (float val, lo_message msg)
3250 {
3251         OSCSurface *sur = get_surface(get_address (msg));
3252         boost::shared_ptr<Stripable> s;
3253         if (sur->expand_enable) {
3254                 s = get_strip (sur->expand, get_address (msg));
3255         } else {
3256                 s = _select;
3257         }
3258         if (s) {
3259                 if (s->comp_speed_controllable()) {
3260                         s->comp_speed_controllable()->set_value (s->comp_speed_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
3261                         return 0;
3262                 }
3263         }
3264         return sel_fail ("comp_speed", 0, get_address (msg));
3265 }
3266
3267 int
3268 OSC::sel_comp_mode (float val, lo_message msg)
3269 {
3270         OSCSurface *sur = get_surface(get_address (msg));
3271         boost::shared_ptr<Stripable> s;
3272         if (sur->expand_enable) {
3273                 s = get_strip (sur->expand, get_address (msg));
3274         } else {
3275                 s = _select;
3276         }
3277         if (s) {
3278                 if (s->comp_mode_controllable()) {
3279                         s->comp_mode_controllable()->set_value (s->comp_mode_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
3280                         return 0;
3281                 }
3282         }
3283         return sel_fail ("comp_mode", 0, get_address (msg));
3284 }
3285
3286 int
3287 OSC::sel_comp_makeup (float val, lo_message msg)
3288 {
3289         OSCSurface *sur = get_surface(get_address (msg));
3290         boost::shared_ptr<Stripable> s;
3291         if (sur->expand_enable) {
3292                 s = get_strip (sur->expand, get_address (msg));
3293         } else {
3294                 s = _select;
3295         }
3296         if (s) {
3297                 if (s->comp_makeup_controllable()) {
3298                         s->comp_makeup_controllable()->set_value (s->comp_makeup_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
3299                         return 0;
3300                 }
3301         }
3302         return sel_fail ("comp_makeup", 0, get_address (msg));
3303 }
3304
3305 // EQ control
3306
3307 int
3308 OSC::sel_eq_enable (float val, lo_message msg)
3309 {
3310         OSCSurface *sur = get_surface(get_address (msg));
3311         boost::shared_ptr<Stripable> s;
3312         if (sur->expand_enable) {
3313                 s = get_strip (sur->expand, get_address (msg));
3314         } else {
3315                 s = _select;
3316         }
3317         if (s) {
3318                 if (s->eq_enable_controllable()) {
3319                         s->eq_enable_controllable()->set_value (s->eq_enable_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
3320                         return 0;
3321                 }
3322         }
3323         return sel_fail ("eq_enable", 0, get_address (msg));
3324 }
3325
3326 int
3327 OSC::sel_eq_hpf (float val, lo_message msg)
3328 {
3329         OSCSurface *sur = get_surface(get_address (msg));
3330         boost::shared_ptr<Stripable> s;
3331         if (sur->expand_enable) {
3332                 s = get_strip (sur->expand, get_address (msg));
3333         } else {
3334                 s = _select;
3335         }
3336         if (s) {
3337                 if (s->eq_hpf_controllable()) {
3338                         s->eq_hpf_controllable()->set_value (s->eq_hpf_controllable()->interface_to_internal (val), PBD::Controllable::NoGroup);
3339                         return 0;
3340                 }
3341         }
3342         return sel_fail ("eq_hpf", 0, get_address (msg));
3343 }
3344
3345 int
3346 OSC::sel_eq_gain (int id, float val, lo_message msg)
3347 {
3348         OSCSurface *sur = get_surface(get_address (msg));
3349         boost::shared_ptr<Stripable> s;
3350         if (sur->expand_enable) {
3351                 s = get_strip (sur->expand, get_address (msg));
3352         } else {
3353                 s = _select;
3354         }
3355         if (s) {
3356                 if (id > 0) {
3357                         --id;
3358                 }
3359                 if (s->eq_gain_controllable (id)) {
3360                         s->eq_gain_controllable (id)->set_value (s->eq_gain_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
3361                         return 0;
3362                 }
3363         }
3364         return sel_send_fail ("eq_gain", id + 1, 0, get_address (msg));
3365 }
3366
3367 int
3368 OSC::sel_eq_freq (int id, float val, lo_message msg)
3369 {
3370         OSCSurface *sur = get_surface(get_address (msg));
3371         boost::shared_ptr<Stripable> s;
3372         if (sur->expand_enable) {
3373                 s = get_strip (sur->expand, get_address (msg));
3374         } else {
3375                 s = _select;
3376         }
3377         if (s) {
3378                 if (id > 0) {
3379                         --id;
3380                 }
3381                 if (s->eq_freq_controllable (id)) {
3382                         s->eq_freq_controllable (id)->set_value (s->eq_freq_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
3383                         return 0;
3384                 }
3385         }
3386         return sel_send_fail ("eq_freq", id + 1, 0, get_address (msg));
3387 }
3388
3389 int
3390 OSC::sel_eq_q (int id, float val, lo_message msg)
3391 {
3392         OSCSurface *sur = get_surface(get_address (msg));
3393         boost::shared_ptr<Stripable> s;
3394         if (sur->expand_enable) {
3395                 s = get_strip (sur->expand, get_address (msg));
3396         } else {
3397                 s = _select;
3398         }
3399         if (s) {
3400                 if (id > 0) {
3401                         --id;
3402                 }
3403                 if (s->eq_q_controllable (id)) {
3404                         s->eq_q_controllable (id)->set_value (s->eq_q_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
3405                         return 0;
3406                 }
3407         }
3408         return sel_send_fail ("eq_q", id + 1, 0, get_address (msg));
3409 }
3410
3411 int
3412 OSC::sel_eq_shape (int id, float val, lo_message msg)
3413 {
3414         OSCSurface *sur = get_surface(get_address (msg));
3415         boost::shared_ptr<Stripable> s;
3416         if (sur->expand_enable) {
3417                 s = get_strip (sur->expand, get_address (msg));
3418         } else {
3419                 s = _select;
3420         }
3421         if (s) {
3422                 if (id > 0) {
3423                         --id;
3424                 }
3425                 if (s->eq_shape_controllable (id)) {
3426                         s->eq_shape_controllable (id)->set_value (s->eq_shape_controllable(id)->interface_to_internal (val), PBD::Controllable::NoGroup);
3427                         return 0;
3428                 }
3429         }
3430         return sel_send_fail ("eq_shape", id + 1, 0, get_address (msg));
3431 }
3432
3433 void
3434 OSC::gui_selection_changed ()
3435 {
3436         boost::shared_ptr<Stripable> strip = ControlProtocol::first_selected_stripable();
3437
3438         if (strip) {
3439                 _select = strip;
3440                 for (uint32_t it = 0; it < _surface.size(); ++it) {
3441                         OSCSurface* sur = &_surface[it];
3442                         if(!sur->expand_enable) {
3443                                 lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
3444                                 _strip_select (strip, addr);
3445                         }
3446                 }
3447         }
3448 }
3449
3450 // timer callbacks
3451 bool
3452 OSC::periodic (void)
3453 {
3454         if (!tick) {
3455                 Glib::usleep(100); // let flurry of signals subside
3456                 if (global_init) {
3457                         for (uint32_t it = 0; it < _surface.size(); it++) {
3458                                 OSCSurface* sur = &_surface[it];
3459                                 lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
3460                                 global_feedback (sur->feedback, addr, sur->gainmode);
3461                         }
3462                         global_init = false;
3463                         tick = true;
3464                 }
3465                 if (bank_dirty) {
3466                         _recalcbanks ();
3467                         bank_dirty = false;
3468                         tick = true;
3469                 }
3470         }
3471
3472         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end(); x++) {
3473
3474                 OSCGlobalObserver* go;
3475
3476                 if ((go = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
3477                         go->tick();
3478                 }
3479         }
3480         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); x++) {
3481
3482                 OSCRouteObserver* ro;
3483
3484                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
3485                         ro->tick();
3486                 }
3487         }
3488         for (uint32_t it = 0; it < _surface.size(); it++) {
3489                 OSCSurface* sur = &_surface[it];
3490                 OSCSelectObserver* so;
3491                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
3492                         so->tick();
3493                 }
3494         }
3495         for (CueObservers::iterator x = cue_observers.begin(); x != cue_observers.end(); x++) {
3496
3497                 OSCCueObserver* co;
3498
3499                 if ((co = dynamic_cast<OSCCueObserver*>(*x)) != 0) {
3500                         co->tick();
3501                 }
3502         }
3503         return true;
3504 }
3505
3506 int
3507 OSC::route_send_fail (string path, uint32_t ssid, float val, lo_address addr)
3508 {
3509         OSCSurface *sur = get_surface(addr);
3510
3511         ostringstream os;
3512         lo_message reply;
3513         if (ssid) {
3514                 reply = lo_message_new ();
3515                 if (sur->feedback[2]) {
3516                         os << "/strip/" << path << "/" << ssid;
3517                 } else {
3518                         os << "/strip/" << path;
3519                         lo_message_add_int32 (reply, ssid);
3520                 }
3521                 string str_pth = os.str();
3522                 lo_message_add_float (reply, (float) val);
3523
3524                 lo_send_message (addr, str_pth.c_str(), reply);
3525                 lo_message_free (reply);
3526         }
3527         if ((_select == get_strip (ssid, addr)) || ((sur->expand == ssid) && (sur->expand_enable))) {
3528                 os.str("");
3529                 os << "/select/" << path;
3530                 string sel_pth = os.str();
3531                 reply = lo_message_new ();
3532                 lo_message_add_float (reply, (float) val);
3533                 lo_send_message (addr, sel_pth.c_str(), reply);
3534                 lo_message_free (reply);
3535         }
3536
3537         return 0;
3538 }
3539
3540 int
3541 OSC::sel_fail (string path, float val, lo_address addr)
3542 {
3543         ostringstream os;
3544         os.str("");
3545         os << "/select/" << path;
3546         string sel_pth = os.str();
3547         lo_message reply = lo_message_new ();
3548         lo_message_add_float (reply, (float) val);
3549         lo_send_message (addr, sel_pth.c_str(), reply);
3550         lo_message_free (reply);
3551
3552         return 0;
3553 }
3554
3555 int
3556 OSC::sel_send_fail (string path, uint32_t id, float val, lo_address addr)
3557 {
3558         OSCSurface *sur = get_surface(addr);
3559
3560         ostringstream os;
3561         lo_message reply;
3562         reply = lo_message_new ();
3563         if (sur->feedback[2]) {
3564                 os << "/select/" << path << "/" << id;
3565         } else {
3566                 os << "/select/" << path;
3567                 lo_message_add_int32 (reply, id);
3568         }
3569         string str_pth = os.str();
3570         lo_message_add_float (reply, (float) val);
3571
3572         lo_send_message (addr, str_pth.c_str(), reply);
3573         lo_message_free (reply);
3574
3575         return 0;
3576 }
3577
3578 XMLNode&
3579 OSC::get_state ()
3580 {
3581         XMLNode& node (ControlProtocol::get_state());
3582         node.add_property("debugmode", (int) _debugmode); // TODO: enum2str
3583         node.add_property ("address-only", address_only);
3584         node.add_property ("remote-port", remote_port);
3585         node.add_property ("banksize", default_banksize);
3586         node.add_property ("striptypes", default_strip);
3587         node.add_property ("feedback", default_feedback);
3588         node.add_property ("gainmode", default_gainmode);
3589         if (_surface.size()) {
3590                 XMLNode* config = new XMLNode (X_("Configurations"));
3591                 for (uint32_t it = 0; it < _surface.size(); ++it) {
3592                         OSCSurface* sur = &_surface[it];
3593                         XMLNode* devnode = new XMLNode (X_("Configuration"));
3594                         devnode->add_property (X_("url"), sur->remote_url);
3595                         devnode->add_property (X_("bank-size"), sur->bank_size);
3596                         devnode->add_property (X_("strip-types"), sur->strip_types.to_ulong());
3597                         devnode->add_property (X_("feedback"), sur->feedback.to_ulong());
3598                         devnode->add_property (X_("gainmode"), sur->gainmode);
3599                         config->add_child_nocopy (*devnode);
3600                 }
3601                 node.add_child_nocopy (*config);
3602         }
3603         return node;
3604 }
3605
3606 int
3607 OSC::set_state (const XMLNode& node, int version)
3608 {
3609         if (ControlProtocol::set_state (node, version)) {
3610                 return -1;
3611         }
3612         XMLProperty const * p = node.property (X_("debugmode"));
3613         if (p) {
3614                 _debugmode = OSCDebugMode (PBD::atoi(p->value ()));
3615         }
3616         p = node.property (X_("address-only"));
3617         if (p) {
3618                 address_only = OSCDebugMode (PBD::atoi(p->value ()));
3619         }
3620         p = node.property (X_("remote-port"));
3621         if (p) {
3622                 remote_port = p->value ();
3623         }
3624         p = node.property (X_("banksize"));
3625         if (p) {
3626                 default_banksize = OSCDebugMode (PBD::atoi(p->value ()));
3627         }
3628         p = node.property (X_("striptypes"));
3629         if (p) {
3630                 default_strip = OSCDebugMode (PBD::atoi(p->value ()));
3631         }
3632         p = node.property (X_("feedback"));
3633         if (p) {
3634                 default_feedback = OSCDebugMode (PBD::atoi(p->value ()));
3635         }
3636         p = node.property (X_("gainmode"));
3637         if (p) {
3638                 default_gainmode = OSCDebugMode (PBD::atoi(p->value ()));
3639         }
3640         XMLNode* cnode = node.child (X_("Configurations"));
3641
3642         if (cnode) {
3643                 XMLNodeList const& devices = cnode->children();
3644                 for (XMLNodeList::const_iterator d = devices.begin(); d != devices.end(); ++d) {
3645                         XMLProperty const * prop = (*d)->property (X_("url"));
3646                         if (prop) {
3647                                 OSCSurface s;
3648                                 bank_dirty = true;
3649                                 s.remote_url = prop->value();
3650                                 prop = (*d)->property (X_("bank-size"));
3651                                 if (prop) {
3652                                         s.bank_size = atoi (prop->value().c_str());
3653                                 }
3654                                 prop = (*d)->property (X_("strip-types"));
3655                                 if (prop) {
3656                                         s.strip_types = atoi (prop->value().c_str());
3657                                 }
3658                                 prop = (*d)->property (X_("feedback"));
3659                                 if (prop) {
3660                                         s.feedback = atoi (prop->value().c_str());
3661                                 }
3662                                 prop = (*d)->property (X_("gainmode"));
3663                                 if (prop) {
3664                                         s.gainmode = atoi (prop->value().c_str());
3665                                 }
3666                                 s.bank = 1;
3667                                 s.sel_obs = 0;
3668                                 s.expand = 0;
3669                                 s.expand_enable = false;
3670                                 s.strips = get_sorted_stripables(s.strip_types);
3671                                 s.nstrips = s.strips.size();
3672                                 _surface.push_back (s);
3673                         }
3674                 }
3675         }
3676         global_init = true;
3677         tick = false;
3678
3679         return 0;
3680 }
3681
3682 // predicate for sort call in get_sorted_stripables
3683 struct StripableByPresentationOrder
3684 {
3685         bool operator () (const boost::shared_ptr<Stripable> & a, const boost::shared_ptr<Stripable> & b) const
3686         {
3687                 return a->presentation_info().order() < b->presentation_info().order();
3688         }
3689
3690         bool operator () (const Stripable & a, const Stripable & b) const
3691         {
3692                 return a.presentation_info().order() < b.presentation_info().order();
3693         }
3694
3695         bool operator () (const Stripable * a, const Stripable * b) const
3696         {
3697                 return a->presentation_info().order() < b->presentation_info().order();
3698         }
3699 };
3700
3701 OSC::Sorted
3702 OSC::get_sorted_stripables(std::bitset<32> types)
3703 {
3704         Sorted sorted;
3705
3706         // fetch all stripables
3707         StripableList stripables;
3708
3709         session->get_stripables (stripables);
3710
3711         // Look for stripables that match bit in sur->strip_types
3712         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
3713
3714                 boost::shared_ptr<Stripable> s = *it;
3715                 if ((!types[9]) && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
3716                         // do nothing... skip it
3717                 } else {
3718
3719                         if (types[0] && (s->presentation_info().flags() & PresentationInfo::AudioTrack)) {
3720                                 sorted.push_back (s);
3721                         } else
3722                         if (types[1] && (s->presentation_info().flags() & PresentationInfo::MidiTrack)) {
3723                                 sorted.push_back (s);
3724                         } else
3725                         if ((s->presentation_info().flags() & PresentationInfo::AudioBus)) {
3726                                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
3727                                 // r->feeds (session->master_out()) may make more sense
3728                                 if (r->direct_feeds_according_to_reality (session->master_out())) {
3729                                         // this is a bus
3730                                         if (types[2]) {
3731                                                 sorted.push_back (s);
3732                                         }
3733                                 } else {
3734                                         // this is an Aux out
3735                                         if (types[7]) {
3736                                                 sorted.push_back (s);
3737                                         }
3738                                 }
3739                         } else
3740                         if (types[3] && (s->presentation_info().flags() & PresentationInfo::MidiBus)) {
3741                                 sorted.push_back (s);
3742                         } else
3743                         if (types[4] && (s->presentation_info().flags() & PresentationInfo::VCA)) {
3744                                 sorted.push_back (s);
3745                         } else
3746                         if (types[8] && (s->presentation_info().flags() & PresentationInfo::Selected)) {
3747                                 sorted.push_back (s);
3748                         } else
3749                         if (types[9] && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
3750                                 sorted.push_back (s);
3751                         }
3752                 }
3753         }
3754         sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
3755         // Master/Monitor might be anywhere... we put them at the end - Sorry ;)
3756         if (types[5]) {
3757                 sorted.push_back (session->master_out());
3758         }
3759         if (types[6]) {
3760                 sorted.push_back (session->monitor_out());
3761         }
3762         return sorted;
3763 }
3764
3765 int
3766 OSC::cue_parse (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
3767 {
3768         int ret = 1; /* unhandled */
3769
3770         if (!strncmp (path, "/cue/aux", 8)) {
3771                 // set our Aux bus
3772                 cue_set (argv[0]->i, msg);
3773                 ret = 0;
3774         }
3775         else if (!strncmp (path, "/cue/connect", 12)) {
3776                 // switch to next Aux bus
3777                 cue_set (0, msg);
3778                 ret = 0;
3779         }
3780         else if (!strncmp (path, "/cue/next_aux", 13)) {
3781                 // switch to next Aux bus
3782                 cue_next (msg);
3783                 ret = 0;
3784         }
3785         else if (!strncmp (path, "/cue/previous_aux", 17)) {
3786                 // switch to previous Aux bus
3787                 cue_previous (msg);
3788                 ret = 0;
3789         }
3790         else if (!strncmp (path, "/cue/send/fader/", 16) && strlen (path) > 16) {
3791                 int id = atoi (&path[16]);
3792                 cue_send_fader (id, argv[0]->f, msg);
3793                 ret = 0;
3794         }
3795         else if (!strncmp (path, "/cue/send/enable/", 17) && strlen (path) > 17) {
3796                 int id = atoi (&path[17]);
3797                 cue_send_enable (id, argv[0]->f, msg);
3798                 ret = 0;
3799         }
3800         else if (!strncmp (path, "/cue/fader", 10)) {
3801                 cue_aux_fader (argv[0]->f, msg);
3802                 ret = 0;
3803         }
3804         else if (!strncmp (path, "/cue/mute", 9)) {
3805                 cue_aux_mute (argv[0]->f, msg);
3806                 ret = 0;
3807         }
3808
3809         if ((ret && _debugmode == Unhandled)) {
3810                 debugmsg (_("Unhandled OSC cue message"), path, types, argv, argc);
3811         } else if ((!ret && _debugmode == All)) {
3812                 debugmsg (_("OSC cue"), path, types, argv, argc);
3813         }
3814
3815         return ret;
3816 }
3817
3818 int
3819 OSC::cue_set (uint32_t aux, lo_message msg)
3820 {
3821         return _cue_set (aux, get_address (msg));
3822 }
3823
3824 int
3825 OSC::_cue_set (uint32_t aux, lo_address addr)
3826 {
3827         OSCSurface *s = get_surface(addr);
3828         s->bank_size = 0;
3829         s->strip_types = 128;
3830         s->feedback = 0;
3831         s->gainmode = 1;
3832         s->cue = true;
3833         s->aux = aux;
3834         s->strips = get_sorted_stripables(s->strip_types);
3835
3836         s->nstrips = s->strips.size();
3837         // get rid of any old CueObsevers for this address
3838         cueobserver_connections.drop_connections ();
3839         CueObservers::iterator x;
3840         for (x = cue_observers.begin(); x != cue_observers.end();) {
3841
3842                 OSCCueObserver* co;
3843
3844                 if ((co = dynamic_cast<OSCCueObserver*>(*x)) != 0) {
3845
3846                         int res = strcmp(lo_address_get_url(co->address()), lo_address_get_url(addr));
3847
3848                         if (res == 0) {
3849                                 delete *x;
3850                                 x = cue_observers.erase (x);
3851                         } else {
3852                                 ++x;
3853                         }
3854                 } else {
3855                         ++x;
3856                 }
3857         }
3858
3859         // get a list of Auxes
3860         for (uint32_t n = 0; n < s->nstrips; ++n) {
3861                 boost::shared_ptr<Stripable> stp = s->strips[n];
3862                 if (stp) {
3863                         text_message (string_compose ("/cue/name/%1", n+1), stp->name(), addr);
3864                         if (aux == n+1) {
3865                                 // aux must be at least one
3866                                 // need a signal if aux vanishes
3867                                 stp->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::_cue_set, this, aux, addr), this);
3868
3869                                 // make a list of stripables with sends that go to this bus
3870                                 s->sends = cue_get_sorted_stripables(stp, aux, addr);
3871                                 // start cue observer
3872                                 OSCCueObserver* co = new OSCCueObserver (stp, s->sends, addr);
3873                                 cue_observers.push_back (co);
3874                         }
3875
3876                 }
3877         }
3878
3879         return 0;
3880 }
3881
3882 int
3883 OSC::cue_next (lo_message msg)
3884 {
3885         OSCSurface *s = get_surface(get_address (msg));
3886         if (s->aux < s->nstrips) {
3887                 cue_set (s->aux + 1, msg);
3888         } else {
3889                 cue_set (s->nstrips, msg);
3890         }
3891         return 0;
3892 }
3893
3894 int
3895 OSC::cue_previous (lo_message msg)
3896 {
3897         OSCSurface *s = get_surface(get_address (msg));
3898         if (s->aux > 1) {
3899                 cue_set (s->aux - 1, msg);
3900         }
3901         return 0;
3902 }
3903
3904 boost::shared_ptr<Send>
3905 OSC::cue_get_send (uint32_t id, lo_address addr)
3906 {
3907         OSCSurface *s = get_surface(addr);
3908         if (id && s->aux > 0 && id <= s->sends.size()) {
3909                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s->sends[id - 1]);
3910                 boost::shared_ptr<Stripable> aux = get_strip (s->aux, addr);
3911                 if (r && aux) {
3912                         return r->internal_send_for (boost::dynamic_pointer_cast<Route> (aux));
3913                 }
3914         }
3915         return boost::shared_ptr<Send>();
3916
3917 }
3918
3919 int
3920 OSC::cue_aux_fader (float position, lo_message msg)
3921 {
3922         if (!session) return -1;
3923
3924         OSCSurface *sur = get_surface(get_address (msg));
3925         if (sur->cue) {
3926                 if (sur->aux) {
3927                         boost::shared_ptr<Stripable> s = get_strip (sur->aux, get_address (msg));
3928
3929                         if (s) {
3930                                 float abs;
3931                                 abs = slider_position_to_gain_with_max (position, 2.0);
3932                                 if (s->gain_control()) {
3933                                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3934                                         return 0;
3935                                 }
3936                         }
3937                 }
3938         }
3939         return cue_float_message ("/cue/fader", 0, get_address (msg));
3940 }
3941
3942 int
3943 OSC::cue_aux_mute (float state, lo_message msg)
3944 {
3945         if (!session) return -1;
3946
3947         OSCSurface *sur = get_surface(get_address (msg));
3948         if (sur->cue) {
3949                 if (sur->aux) {
3950                         boost::shared_ptr<Stripable> s = get_strip (sur->aux, get_address (msg));
3951                         if (s) {
3952                                 if (s->mute_control()) {
3953                                         s->mute_control()->set_value (state ? 1.0 : 0.0, PBD::Controllable::NoGroup);
3954                                         return 0;
3955                                 }
3956                         }
3957                 }
3958         }
3959         return cue_float_message ("/cue/mute", 0, get_address (msg));
3960 }
3961
3962 int
3963 OSC::cue_send_fader (uint32_t id, float val, lo_message msg)
3964 {
3965         if (!session) {
3966                 return -1;
3967         }
3968         boost::shared_ptr<Send> s = cue_get_send (id, get_address (msg));
3969         float abs;
3970         if (s) {
3971                 if (s->gain_control()) {
3972                         abs = slider_position_to_gain_with_max (val, 2.0);
3973                         s->gain_control()->set_value (abs, PBD::Controllable::NoGroup);
3974                         return 0;
3975                 }
3976         }
3977         return cue_float_message (string_compose ("/cue/send/fader/%1", id), 0, get_address (msg));
3978 }
3979
3980 int
3981 OSC::cue_send_enable (uint32_t id, float state, lo_message msg)
3982 {
3983         if (!session)
3984                 return -1;
3985         boost::shared_ptr<Send> s = cue_get_send (id, get_address (msg));
3986         if (s) {
3987                 if (state) {
3988                         s->activate ();
3989                 } else {
3990                         s->deactivate ();
3991                 }
3992                 return 0;
3993         }
3994         return cue_float_message (string_compose ("/cue/send/enable/%1", id), 0, get_address (msg));
3995 }
3996
3997 int
3998 OSC::cue_float_message (string path, float val, lo_address addr)
3999 {
4000
4001         lo_message reply;
4002         reply = lo_message_new ();
4003         lo_message_add_float (reply, (float) val);
4004
4005         lo_send_message (addr, path.c_str(), reply);
4006         lo_message_free (reply);
4007
4008         return 0;
4009 }
4010
4011 int
4012 OSC::text_message (string path, string val, lo_address addr)
4013 {
4014
4015         lo_message reply;
4016         reply = lo_message_new ();
4017         lo_message_add_string (reply, val.c_str());
4018
4019         lo_send_message (addr, path.c_str(), reply);
4020         lo_message_free (reply);
4021
4022         return 0;
4023 }
4024
4025
4026 // we have to have a sorted list of stripables that have sends pointed at our aux
4027 // we can use the one in osc.cc to get an aux list
4028 OSC::Sorted
4029 OSC::cue_get_sorted_stripables(boost::shared_ptr<Stripable> aux, uint32_t id, lo_message msg)
4030 {
4031         Sorted sorted;
4032         cueobserver_connections.drop_connections ();
4033         // fetch all stripables
4034         StripableList stripables;
4035
4036         session->get_stripables (stripables);
4037
4038         // Look for stripables that have a send to aux
4039         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
4040
4041                 boost::shared_ptr<Stripable> s = *it;
4042                 // we only want routes
4043                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
4044                 if (r) {
4045                         r->processors_changed.connect  (*this, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
4046                         boost::shared_ptr<Send> snd = r->internal_send_for (boost::dynamic_pointer_cast<Route> (aux));
4047                         if (snd) { // test for send to aux
4048                                 sorted.push_back (s);
4049                                 s->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::cue_set, this, id, msg), this);
4050                         }
4051                 }
4052
4053
4054         }
4055         sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
4056
4057         return sorted;
4058 }
4059