Tear down OSC settings GUI, when the protocol is disabled
[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 "pbd/i18n.h"
61
62 using namespace ARDOUR;
63 using namespace std;
64 using namespace Glib;
65 using namespace ArdourSurface;
66
67 #include "pbd/abstract_ui.cc" // instantiate template
68
69 OSC* OSC::_instance = 0;
70
71 #ifdef DEBUG
72 static void error_callback(int num, const char *m, const char *path)
73 {
74         fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
75 }
76 #else
77 static void error_callback(int, const char *, const char *)
78 {
79
80 }
81 #endif
82
83 OSC::OSC (Session& s, uint32_t port)
84         : ControlProtocol (s, X_("Open Sound Control (OSC)"))
85         , AbstractUI<OSCUIRequest> (name())
86         , local_server (0)
87         , remote_server (0)
88         , _port(port)
89         , _ok (true)
90         , _shutdown (false)
91         , _osc_server (0)
92         , _osc_unix_server (0)
93         , _send_route_changes (true)
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::set_feedback (bool yn)
169 {
170         _send_route_changes = yn;
171         return 0;
172 }
173
174 bool
175 OSC::get_feedback () const
176 {
177         return _send_route_changes;
178 }
179
180 int
181 OSC::start ()
182 {
183         char tmpstr[255];
184
185         if (_osc_server) {
186                 /* already started */
187                 return 0;
188         }
189
190         for (int j=0; j < 20; ++j) {
191                 snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
192
193                 //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
194                 //      break;
195                 //}
196
197                 if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
198                         break;
199                 }
200
201 #ifdef DEBUG
202                 cerr << "can't get osc at port: " << _port << endl;
203 #endif
204                 _port++;
205                 continue;
206         }
207
208         if (!_osc_server) {
209                 return 1;
210         }
211
212 #ifdef ARDOUR_OSC_UNIX_SERVER
213
214         // APPEARS sluggish for now
215
216         // attempt to create unix socket server too
217
218         snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
219         int fd = mkstemp(tmpstr);
220
221         if (fd >= 0 ) {
222                 ::g_unlink (tmpstr);
223                 close (fd);
224
225                 _osc_unix_server = lo_server_new (tmpstr, error_callback);
226
227                 if (_osc_unix_server) {
228                         _osc_unix_socket_path = tmpstr;
229                 }
230         }
231 #endif
232
233         PBD::info << "OSC @ " << get_server_url () << endmsg;
234
235         std::string url_file;
236
237         if (find_file (ardour_config_search_path(), "osc_url", url_file)) {
238                 _osc_url_file = url_file;
239                 if (g_file_set_contents (_osc_url_file.c_str(), get_server_url().c_str(), -1, NULL)) {
240                         cerr << "Couldn't write '" <<  _osc_url_file << "'" <<endl;
241                 }
242         }
243
244         register_callbacks();
245
246         session_loaded (*session);
247
248         // lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
249
250         /* startup the event loop thread */
251
252         BaseUI::run ();
253
254         // start timers for metering, timecode and heartbeat.
255         // timecode and metering run at 100
256         Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
257         periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &OSC::periodic));
258         periodic_timeout->attach (main_loop()->get_context());
259
260         // catch changes to selection for GUI_select mode
261         StripableSelectionChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::gui_selection_changed, this), this);
262
263         // catch track reordering
264         // receive routes added
265         session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_routes_added, this, _1), this);
266         // receive VCAs added
267         session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_vca_added, this, _1), this);
268         // order changed
269         PresentationInfo::Change.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::recalcbanks, this), this);
270
271         _select = boost::shared_ptr<Stripable>();
272
273         return 0;
274 }
275
276 void
277 OSC::thread_init ()
278 {
279         pthread_set_name (event_loop_name().c_str());
280
281         if (_osc_unix_server) {
282                 Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
283                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_unix_server));
284                 src->attach (_main_loop->get_context());
285                 local_server = src->gobj();
286                 g_source_ref (local_server);
287         }
288
289         if (_osc_server) {
290 #ifdef PLATFORM_WINDOWS
291                 Glib::RefPtr<IOChannel> chan = Glib::IOChannel::create_from_win32_socket (lo_server_get_socket_fd (_osc_server));
292                 Glib::RefPtr<IOSource> src  = IOSource::create (chan, IO_IN|IO_HUP|IO_ERR);
293 #else
294                 Glib::RefPtr<IOSource> src  = IOSource::create (lo_server_get_socket_fd (_osc_server), IO_IN|IO_HUP|IO_ERR);
295 #endif
296                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_server));
297                 src->attach (_main_loop->get_context());
298                 remote_server = src->gobj();
299                 g_source_ref (remote_server);
300         }
301
302         PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
303         SessionEvent::create_per_thread_pool (event_loop_name(), 128);
304 }
305
306 int
307 OSC::stop ()
308 {
309         /* stop main loop */
310
311         if (local_server) {
312                 g_source_destroy (local_server);
313                 g_source_unref (local_server);
314                 local_server = 0;
315         }
316
317         if (remote_server) {
318                 g_source_destroy (remote_server);
319                 g_source_unref (remote_server);
320                 remote_server = 0;
321         }
322
323         BaseUI::quit ();
324
325         if (_osc_server) {
326                 lo_server_free (_osc_server);
327                 _osc_server = 0;
328         }
329
330         if (_osc_unix_server) {
331                 lo_server_free (_osc_unix_server);
332                 _osc_unix_server = 0;
333         }
334
335         if (!_osc_unix_socket_path.empty()) {
336                 ::g_unlink (_osc_unix_socket_path.c_str());
337         }
338
339         if (!_osc_url_file.empty() ) {
340                 ::g_unlink (_osc_url_file.c_str() );
341         }
342
343         periodic_connection.disconnect ();
344         session_connections.drop_connections ();
345         // Delete any active route observers
346         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
347
348                 OSCRouteObserver* rc;
349
350                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
351                         delete *x;
352                         x = route_observers.erase (x);
353                 } else {
354                         ++x;
355                 }
356         }
357 // Should maybe do global_observers too
358         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end();) {
359
360                 OSCGlobalObserver* gc;
361
362                 if ((gc = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
363                         delete *x;
364                         x = global_observers.erase (x);
365                 } else {
366                         ++x;
367                 }
368         }
369 // delete select observers
370         for (uint32_t it = 0; it < _surface.size(); ++it) {
371                 OSCSurface* sur = &_surface[it];
372                 OSCSelectObserver* so;
373                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
374                         delete so;
375                 }
376         }
377
378         return 0;
379 }
380
381 void
382 OSC::register_callbacks()
383 {
384         lo_server srvs[2];
385         lo_server serv;
386
387         srvs[0] = _osc_server;
388         srvs[1] = _osc_unix_server;
389
390         for (size_t i = 0; i < 2; ++i) {
391
392                 if (!srvs[i]) {
393                         continue;
394                 }
395
396                 serv = srvs[i];
397
398
399 #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this)
400
401                 // Some controls have optional "f" for feedback or touchosc
402                 // http://hexler.net/docs/touchosc-controls-reference
403
404                 REGISTER_CALLBACK (serv, "/set_surface", "iiii", set_surface);
405                 REGISTER_CALLBACK (serv, "/set_surface/feedback", "i", set_surface_feedback);
406                 REGISTER_CALLBACK (serv, "/set_surface/bank_size", "i", set_surface_bank_size);
407                 REGISTER_CALLBACK (serv, "/set_surface/gainmode", "i", set_surface_gainmode);
408                 REGISTER_CALLBACK (serv, "/set_surface/strip_types", "i", set_surface_strip_types);
409                 REGISTER_CALLBACK (serv, "/refresh", "", refresh_surface);
410                 REGISTER_CALLBACK (serv, "/refresh", "f", refresh_surface);
411                 REGISTER_CALLBACK (serv, "/strip/list", "", routes_list);
412                 REGISTER_CALLBACK (serv, "/add_marker", "", add_marker);
413                 REGISTER_CALLBACK (serv, "/add_marker", "f", add_marker);
414                 REGISTER_CALLBACK (serv, "/access_action", "s", access_action);
415                 REGISTER_CALLBACK (serv, "/loop_toggle", "", loop_toggle);
416                 REGISTER_CALLBACK (serv, "/loop_toggle", "f", loop_toggle);
417                 REGISTER_CALLBACK (serv, "/loop_location", "ii", loop_location);
418                 REGISTER_CALLBACK (serv, "/goto_start", "", goto_start);
419                 REGISTER_CALLBACK (serv, "/goto_start", "f", goto_start);
420                 REGISTER_CALLBACK (serv, "/goto_end", "", goto_end);
421                 REGISTER_CALLBACK (serv, "/goto_end", "f", goto_end);
422                 REGISTER_CALLBACK (serv, "/rewind", "", rewind);
423                 REGISTER_CALLBACK (serv, "/rewind", "f", rewind);
424                 REGISTER_CALLBACK (serv, "/ffwd", "", ffwd);
425                 REGISTER_CALLBACK (serv, "/ffwd", "f", ffwd);
426                 REGISTER_CALLBACK (serv, "/transport_stop", "", transport_stop);
427                 REGISTER_CALLBACK (serv, "/transport_stop", "f", transport_stop);
428                 REGISTER_CALLBACK (serv, "/transport_play", "", transport_play);
429                 REGISTER_CALLBACK (serv, "/transport_play", "f", transport_play);
430                 REGISTER_CALLBACK (serv, "/transport_frame", "", transport_frame);
431                 REGISTER_CALLBACK (serv, "/transport_speed", "", transport_speed);
432                 REGISTER_CALLBACK (serv, "/record_enabled", "", record_enabled);
433                 REGISTER_CALLBACK (serv, "/set_transport_speed", "f", set_transport_speed);
434                 // locate ii is position and bool roll
435                 REGISTER_CALLBACK (serv, "/locate", "ii", locate);
436                 REGISTER_CALLBACK (serv, "/save_state", "", save_state);
437                 REGISTER_CALLBACK (serv, "/save_state", "f", save_state);
438                 REGISTER_CALLBACK (serv, "/prev_marker", "", prev_marker);
439                 REGISTER_CALLBACK (serv, "/prev_marker", "f", prev_marker);
440                 REGISTER_CALLBACK (serv, "/next_marker", "", next_marker);
441                 REGISTER_CALLBACK (serv, "/next_marker", "f", next_marker);
442                 REGISTER_CALLBACK (serv, "/undo", "", undo);
443                 REGISTER_CALLBACK (serv, "/undo", "f", undo);
444                 REGISTER_CALLBACK (serv, "/redo", "", redo);
445                 REGISTER_CALLBACK (serv, "/redo", "f", redo);
446                 REGISTER_CALLBACK (serv, "/toggle_punch_in", "", toggle_punch_in);
447                 REGISTER_CALLBACK (serv, "/toggle_punch_in", "f", toggle_punch_in);
448                 REGISTER_CALLBACK (serv, "/toggle_punch_out", "", toggle_punch_out);
449                 REGISTER_CALLBACK (serv, "/toggle_punch_out", "f", toggle_punch_out);
450                 REGISTER_CALLBACK (serv, "/rec_enable_toggle", "", rec_enable_toggle);
451                 REGISTER_CALLBACK (serv, "/rec_enable_toggle", "f", rec_enable_toggle);
452                 REGISTER_CALLBACK (serv, "/toggle_all_rec_enables", "", toggle_all_rec_enables);
453                 REGISTER_CALLBACK (serv, "/toggle_all_rec_enables", "f", toggle_all_rec_enables);
454                 REGISTER_CALLBACK (serv, "/all_tracks_rec_in", "f", all_tracks_rec_in);
455                 REGISTER_CALLBACK (serv, "/all_tracks_rec_out", "f", all_tracks_rec_out);
456                 REGISTER_CALLBACK (serv, "/cancel_all_solos", "f", cancel_all_solos);
457                 REGISTER_CALLBACK (serv, "/remove_marker", "", remove_marker_at_playhead);
458                 REGISTER_CALLBACK (serv, "/remove_marker", "f", remove_marker_at_playhead);
459                 REGISTER_CALLBACK (serv, "/jump_bars", "f", jump_by_bars);
460                 REGISTER_CALLBACK (serv, "/jump_seconds", "f", jump_by_seconds);
461                 REGISTER_CALLBACK (serv, "/mark_in", "", mark_in);
462                 REGISTER_CALLBACK (serv, "/mark_in", "f", mark_in);
463                 REGISTER_CALLBACK (serv, "/mark_out", "", mark_out);
464                 REGISTER_CALLBACK (serv, "/mark_out", "f", mark_out);
465                 REGISTER_CALLBACK (serv, "/toggle_click", "", toggle_click);
466                 REGISTER_CALLBACK (serv, "/toggle_click", "f", toggle_click);
467                 REGISTER_CALLBACK (serv, "/midi_panic", "", midi_panic);
468                 REGISTER_CALLBACK (serv, "/midi_panic", "f", midi_panic);
469                 REGISTER_CALLBACK (serv, "/toggle_roll", "", toggle_roll);
470                 REGISTER_CALLBACK (serv, "/toggle_roll", "f", toggle_roll);
471                 REGISTER_CALLBACK (serv, "/stop_forget", "", stop_forget);
472                 REGISTER_CALLBACK (serv, "/stop_forget", "f", stop_forget);
473                 REGISTER_CALLBACK (serv, "/set_punch_range", "", set_punch_range);
474                 REGISTER_CALLBACK (serv, "/set_punch_range", "f", set_punch_range);
475                 REGISTER_CALLBACK (serv, "/set_loop_range", "", set_loop_range);
476                 REGISTER_CALLBACK (serv, "/set_loop_range", "f", set_loop_range);
477                 REGISTER_CALLBACK (serv, "/set_session_range", "", set_session_range);
478                 REGISTER_CALLBACK (serv, "/set_session_range", "f", set_session_range);
479                 // /toggle_monitor_* not working (comented out)
480                 REGISTER_CALLBACK (serv, "/toggle_monitor_mute", "", toggle_monitor_mute);
481                 REGISTER_CALLBACK (serv, "/toggle_monitor_mute", "f", toggle_monitor_mute);
482                 REGISTER_CALLBACK (serv, "/toggle_monitor_dim", "", toggle_monitor_dim);
483                 REGISTER_CALLBACK (serv, "/toggle_monitor_dim", "f", toggle_monitor_dim);
484                 REGISTER_CALLBACK (serv, "/toggle_monitor_mono", "", toggle_monitor_mono);
485                 REGISTER_CALLBACK (serv, "/toggle_monitor_mono", "f", toggle_monitor_mono);
486                 REGISTER_CALLBACK (serv, "/quick_snapshot_switch", "", quick_snapshot_switch);
487                 REGISTER_CALLBACK (serv, "/quick_snapshot_switch", "f", quick_snapshot_switch);
488                 REGISTER_CALLBACK (serv, "/quick_snapshot_stay", "", quick_snapshot_stay);
489                 REGISTER_CALLBACK (serv, "/quick_snapshot_stay", "f", quick_snapshot_stay);
490                 REGISTER_CALLBACK (serv, "/fit_1_track", "", fit_1_track);
491                 REGISTER_CALLBACK (serv, "/fit_1_track", "f", fit_1_track);
492                 REGISTER_CALLBACK (serv, "/fit_2_tracks", "", fit_2_tracks);
493                 REGISTER_CALLBACK (serv, "/fit_2_tracks", "f", fit_2_tracks);
494                 REGISTER_CALLBACK (serv, "/fit_4_tracks", "", fit_4_tracks);
495                 REGISTER_CALLBACK (serv, "/fit_4_tracks", "f", fit_4_tracks);
496                 REGISTER_CALLBACK (serv, "/fit_8_tracks", "", fit_8_tracks);
497                 REGISTER_CALLBACK (serv, "/fit_8_tracks", "f", fit_8_tracks);
498                 REGISTER_CALLBACK (serv, "/fit_16_tracks", "", fit_16_tracks);
499                 REGISTER_CALLBACK (serv, "/fit_16_tracks", "f", fit_16_tracks);
500                 REGISTER_CALLBACK (serv, "/fit_32_tracks", "", fit_32_tracks);
501                 REGISTER_CALLBACK (serv, "/fit_32_tracks", "f", fit_32_tracks);
502                 REGISTER_CALLBACK (serv, "/fit_all_tracks", "", fit_all_tracks);
503                 REGISTER_CALLBACK (serv, "/fit_all_tracks", "f", fit_all_tracks);
504                 REGISTER_CALLBACK (serv, "/zoom_100_ms", "", zoom_100_ms);
505                 REGISTER_CALLBACK (serv, "/zoom_100_ms", "f", zoom_100_ms);
506                 REGISTER_CALLBACK (serv, "/zoom_1_sec", "", zoom_1_sec);
507                 REGISTER_CALLBACK (serv, "/zoom_1_sec", "f", zoom_1_sec);
508                 REGISTER_CALLBACK (serv, "/zoom_10_sec", "", zoom_10_sec);
509                 REGISTER_CALLBACK (serv, "/zoom_10_sec", "f", zoom_10_sec);
510                 REGISTER_CALLBACK (serv, "/zoom_1_min", "", zoom_1_min);
511                 REGISTER_CALLBACK (serv, "/zoom_1_min", "f", zoom_1_min);
512                 REGISTER_CALLBACK (serv, "/zoom_5_min", "", zoom_5_min);
513                 REGISTER_CALLBACK (serv, "/zoom_5_min", "f", zoom_5_min);
514                 REGISTER_CALLBACK (serv, "/zoom_10_min", "", zoom_10_min);
515                 REGISTER_CALLBACK (serv, "/zoom_10_min", "f", zoom_10_min);
516                 REGISTER_CALLBACK (serv, "/zoom_to_session", "", zoom_to_session);
517                 REGISTER_CALLBACK (serv, "/zoom_to_session", "f", zoom_to_session);
518                 REGISTER_CALLBACK (serv, "/temporal_zoom_in", "f", temporal_zoom_in);
519                 REGISTER_CALLBACK (serv, "/temporal_zoom_in", "", temporal_zoom_in);
520                 REGISTER_CALLBACK (serv, "/temporal_zoom_out", "", temporal_zoom_out);
521                 REGISTER_CALLBACK (serv, "/temporal_zoom_out", "f", temporal_zoom_out);
522                 REGISTER_CALLBACK (serv, "/scroll_up_1_track", "f", scroll_up_1_track);
523                 REGISTER_CALLBACK (serv, "/scroll_up_1_track", "", scroll_up_1_track);
524                 REGISTER_CALLBACK (serv, "/scroll_dn_1_track", "f", scroll_dn_1_track);
525                 REGISTER_CALLBACK (serv, "/scroll_dn_1_track", "", scroll_dn_1_track);
526                 REGISTER_CALLBACK (serv, "/scroll_up_1_page", "f", scroll_up_1_page);
527                 REGISTER_CALLBACK (serv, "/scroll_up_1_page", "", scroll_up_1_page);
528                 REGISTER_CALLBACK (serv, "/scroll_dn_1_page", "f", scroll_dn_1_page);
529                 REGISTER_CALLBACK (serv, "/scroll_dn_1_page", "", scroll_dn_1_page);
530                 REGISTER_CALLBACK (serv, "/bank_up", "", bank_up);
531                 REGISTER_CALLBACK (serv, "/bank_up", "f", bank_up);
532                 REGISTER_CALLBACK (serv, "/bank_down", "", bank_down);
533                 REGISTER_CALLBACK (serv, "/bank_down", "f", bank_down);
534
535                 // controls for "special" strips
536                 REGISTER_CALLBACK (serv, "/master/gain", "f", master_set_gain);
537                 REGISTER_CALLBACK (serv, "/master/fader", "f", master_set_fader);
538                 REGISTER_CALLBACK (serv, "/master/mute", "i", master_set_mute);
539                 REGISTER_CALLBACK (serv, "/master/trimdB", "f", master_set_trim);
540                 REGISTER_CALLBACK (serv, "/master/pan_stereo_position", "f", master_set_pan_stereo_position);
541                 REGISTER_CALLBACK (serv, "/monitor/gain", "f", monitor_set_gain);
542                 REGISTER_CALLBACK (serv, "/monitor/fader", "f", monitor_set_fader);
543
544                 // Controls for the Selected strip
545                 REGISTER_CALLBACK (serv, "/select/recenable", "i", sel_recenable);
546                 REGISTER_CALLBACK (serv, "/select/record_safe", "i", sel_recsafe);
547                 REGISTER_CALLBACK (serv, "/select/mute", "i", sel_mute);
548                 REGISTER_CALLBACK (serv, "/select/solo", "i", sel_solo);
549                 REGISTER_CALLBACK (serv, "/select/solo_iso", "i", sel_solo_iso);
550                 REGISTER_CALLBACK (serv, "/select/solo_safe", "i", sel_solo_safe);
551                 REGISTER_CALLBACK (serv, "/select/monitor_input", "i", sel_monitor_input);
552                 REGISTER_CALLBACK (serv, "/select/monitor_disk", "i", sel_monitor_disk);
553                 REGISTER_CALLBACK (serv, "/select/polarity", "i", sel_phase);
554                 REGISTER_CALLBACK (serv, "/select/gain", "f", sel_gain);
555                 REGISTER_CALLBACK (serv, "/select/fader", "f", sel_fader);
556                 REGISTER_CALLBACK (serv, "/select/trimdB", "f", sel_trim);
557                 REGISTER_CALLBACK (serv, "/select/pan_stereo_position", "f", sel_pan_position);
558                 REGISTER_CALLBACK (serv, "/select/pan_stereo_width", "f", sel_pan_width);
559                 REGISTER_CALLBACK (serv, "/select/send_gain", "if", sel_sendgain);
560                 REGISTER_CALLBACK (serv, "/select/send_fader", "if", sel_sendfader);
561                 REGISTER_CALLBACK (serv, "/select/send_enable", "if", sel_sendenable);
562                 REGISTER_CALLBACK (serv, "/select/expand", "i", sel_expand);
563                 REGISTER_CALLBACK (serv, "/select/pan_elevation_position", "f", sel_pan_elevation);
564                 REGISTER_CALLBACK (serv, "/select/pan_frontback_position", "f", sel_pan_frontback);
565                 REGISTER_CALLBACK (serv, "/select/pan_lfe_control", "f", sel_pan_lfe);
566                 REGISTER_CALLBACK (serv, "/select/comp_enable", "f", sel_comp_enable);
567                 REGISTER_CALLBACK (serv, "/select/comp_threshold", "f", sel_comp_threshold);
568                 REGISTER_CALLBACK (serv, "/select/comp_speed", "f", sel_comp_speed);
569                 REGISTER_CALLBACK (serv, "/select/comp_mode", "f", sel_comp_mode);
570                 REGISTER_CALLBACK (serv, "/select/comp_makeup", "f", sel_comp_makeup);
571                 REGISTER_CALLBACK (serv, "/select/eq_enable", "f", sel_eq_enable);
572                 REGISTER_CALLBACK (serv, "/select/eq_hpf", "f", sel_eq_hpf);
573                 REGISTER_CALLBACK (serv, "/select/eq_gain", "if", sel_eq_gain);
574                 REGISTER_CALLBACK (serv, "/select/eq_freq", "if", sel_eq_freq);
575                 REGISTER_CALLBACK (serv, "/select/eq_q", "if", sel_eq_q);
576                 REGISTER_CALLBACK (serv, "/select/eq_shape", "if", sel_eq_shape);
577
578                 /* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these  */ 
579                 REGISTER_CALLBACK (serv, "/strip/mute", "ii", route_mute);
580                 REGISTER_CALLBACK (serv, "/strip/solo", "ii", route_solo);
581                 REGISTER_CALLBACK (serv, "/strip/solo_iso", "ii", route_solo_iso);
582                 REGISTER_CALLBACK (serv, "/strip/solo_safe", "ii", route_solo_safe);
583                 REGISTER_CALLBACK (serv, "/strip/recenable", "ii", route_recenable);
584                 REGISTER_CALLBACK (serv, "/strip/record_safe", "ii", route_recsafe);
585                 REGISTER_CALLBACK (serv, "/strip/monitor_input", "ii", route_monitor_input);
586                 REGISTER_CALLBACK (serv, "/strip/monitor_disk", "ii", route_monitor_disk);
587                 REGISTER_CALLBACK (serv, "/strip/expand", "ii", strip_expand);
588                 REGISTER_CALLBACK (serv, "/strip/select", "ii", strip_gui_select);
589                 REGISTER_CALLBACK (serv, "/strip/polarity", "ii", strip_phase);
590                 REGISTER_CALLBACK (serv, "/strip/gain", "if", route_set_gain_dB);
591                 REGISTER_CALLBACK (serv, "/strip/fader", "if", route_set_gain_fader);
592                 REGISTER_CALLBACK (serv, "/strip/trimdB", "if", route_set_trim_dB);
593                 REGISTER_CALLBACK (serv, "/strip/pan_stereo_position", "if", route_set_pan_stereo_position);
594                 REGISTER_CALLBACK (serv, "/strip/pan_stereo_width", "if", route_set_pan_stereo_width);
595                 REGISTER_CALLBACK (serv, "/strip/plugin/parameter", "iiif", route_plugin_parameter);
596                 // prints to cerr only
597                 REGISTER_CALLBACK (serv, "/strip/plugin/parameter/print", "iii", route_plugin_parameter_print);
598                 REGISTER_CALLBACK (serv, "/strip/plugin/activate", "ii", route_plugin_activate);
599                 REGISTER_CALLBACK (serv, "/strip/plugin/deactivate", "ii", route_plugin_deactivate);
600                 REGISTER_CALLBACK (serv, "/strip/send/gain", "iif", route_set_send_gain_dB);
601                 REGISTER_CALLBACK (serv, "/strip/send/fader", "iif", route_set_send_fader);
602                 REGISTER_CALLBACK (serv, "/strip/send/enable", "iif", route_set_send_enable);
603                 REGISTER_CALLBACK(serv, "/strip/name", "is", route_rename);
604                 REGISTER_CALLBACK(serv, "/strip/sends", "i", route_get_sends);
605                 REGISTER_CALLBACK(serv, "/strip/receives", "i", route_get_receives);                
606                 REGISTER_CALLBACK(serv, "/strip/plugin/list", "i", route_plugin_list);
607                 REGISTER_CALLBACK(serv, "/strip/plugin/descriptor", "ii", route_plugin_descriptor);
608                 REGISTER_CALLBACK(serv, "/strip/plugin/reset", "ii", route_plugin_reset);
609
610                 /* still not-really-standardized query interface */
611                 //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
612                 //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
613
614                 // un/register_update args= s:ctrl s:returl s:retpath
615                 //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
616                 //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
617                 //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
618                 //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
619
620                 /* this is a special catchall handler,
621                  * register at the end so this is only called if no
622                  * other handler matches (used for debug) */
623                 lo_server_add_method (serv, 0, 0, _catchall, this);
624         }
625 }
626
627 bool
628 OSC::osc_input_handler (IOCondition ioc, lo_server srv)
629 {
630         if (ioc & ~IO_IN) {
631                 return false;
632         }
633
634         if (ioc & IO_IN) {
635                 lo_server_recv (srv);
636         }
637
638         return true;
639 }
640
641 std::string
642 OSC::get_server_url()
643 {
644         string url;
645         char * urlstr;
646
647         if (_osc_server) {
648                 urlstr = lo_server_get_url (_osc_server);
649                 url = urlstr;
650                 free (urlstr);
651         }
652
653         return url;
654 }
655
656 std::string
657 OSC::get_unix_server_url()
658 {
659         string url;
660         char * urlstr;
661
662         if (_osc_unix_server) {
663                 urlstr = lo_server_get_url (_osc_unix_server);
664                 url = urlstr;
665                 free (urlstr);
666         }
667
668         return url;
669 }
670
671 void
672 OSC::gui_changed ()
673 {
674         session->set_dirty();
675 }
676
677 void
678 OSC::listen_to_route (boost::shared_ptr<Stripable> strip, lo_address addr)
679 {
680         if (!strip) {
681                 return;
682         }
683         /* avoid duplicate listens */
684
685         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); ++x) {
686
687                 OSCRouteObserver* ro;
688
689                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
690
691                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
692
693                         if (ro->strip() == strip && res == 0) {
694                                 return;
695                         }
696                 }
697         }
698
699         OSCSurface *s = get_surface(addr);
700         uint32_t ssid = get_sid (strip, addr);
701         OSCRouteObserver* o = new OSCRouteObserver (strip, addr, ssid, s->gainmode, s->feedback);
702         route_observers.push_back (o);
703
704         strip->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::route_lost, this, boost::weak_ptr<Stripable> (strip)), this);
705 }
706
707 void
708 OSC::route_lost (boost::weak_ptr<Stripable> wr)
709 {
710         tick = false;
711         drop_route (wr);
712         bank_dirty = true;
713 }
714
715 void
716 OSC::drop_route (boost::weak_ptr<Stripable> wr)
717 {
718         boost::shared_ptr<Stripable> r = wr.lock ();
719
720         if (!r) {
721                 return;
722         }
723
724         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
725
726                 OSCRouteObserver* rc;
727
728                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
729
730                         if (rc->strip() == r) {
731                                 delete *x;
732                                 x = route_observers.erase (x);
733                         } else {
734                                 ++x;
735                         }
736                 } else {
737                         ++x;
738                 }
739         }
740 }
741
742 void
743 OSC::end_listen (boost::shared_ptr<Stripable> r, lo_address addr)
744 {
745         RouteObservers::iterator x;
746
747         // Remove the route observers
748         for (x = route_observers.begin(); x != route_observers.end();) {
749
750                 OSCRouteObserver* ro;
751
752                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
753
754                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
755
756                         if (ro->strip() == r && res == 0) {
757                                 delete *x;
758                                 x = route_observers.erase (x);
759                         }
760                         else {
761                                 ++x;
762                         }
763                 }
764                 else {
765                         ++x;
766                 }
767         }
768 }
769
770 void
771 OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg)
772 {
773         char* subpath;
774
775         subpath = (char*) malloc (len-15+1);
776         memcpy (subpath, path, len-15);
777         subpath[len-15] = '\0';
778
779         send_current_value (subpath, argv, argc, msg);
780
781         free (subpath);
782 }
783
784 void
785 OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg)
786 {
787         if (!session) {
788                 return;
789         }
790
791         lo_message reply = lo_message_new ();
792         boost::shared_ptr<Route> r;
793         int id;
794
795         lo_message_add_string (reply, path);
796
797         if (argc == 0) {
798                 lo_message_add_string (reply, "bad syntax");
799         } else {
800                 id = argv[0]->i;
801                 r = session->get_remote_nth_route (id);
802
803                 if (!r) {
804                         lo_message_add_string (reply, "not found");
805                 } else {
806
807                         if (strcmp (path, "/strip/state") == 0) {
808
809                                 if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
810                                         lo_message_add_string (reply, "AT");
811                                 } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
812                                         lo_message_add_string (reply, "MT");
813                                 } else {
814                                         lo_message_add_string (reply, "B");
815                                 }
816
817                                 lo_message_add_string (reply, r->name().c_str());
818                                 lo_message_add_int32 (reply, r->n_inputs().n_audio());
819                                 lo_message_add_int32 (reply, r->n_outputs().n_audio());
820                                 lo_message_add_int32 (reply, r->muted());
821                                 lo_message_add_int32 (reply, r->soloed());
822
823                         } else if (strcmp (path, "/strip/mute") == 0) {
824
825                                 lo_message_add_int32 (reply, (float) r->muted());
826
827                         } else if (strcmp (path, "/strip/solo") == 0) {
828
829                                 lo_message_add_int32 (reply, r->soloed());
830                         }
831                 }
832         }
833
834         lo_send_message (get_address (msg), "#reply", reply);
835         lo_message_free (reply);
836 }
837
838 int
839 OSC::_catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data)
840 {
841         return ((OSC*)user_data)->catchall (path, types, argv, argc, data);
842 }
843
844 int
845 OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
846 {
847         size_t len;
848         int ret = 1; /* unhandled */
849
850         //cerr << "Received a message, path = " << path << " types = \""
851         //     << (types ? types : "NULL") << '"' << endl;
852
853         /* 15 for /#current_value plus 2 for /<path> */
854
855         len = strlen (path);
856
857         if (len >= 17 && !strcmp (&path[len-15], "/#current_value")) {
858                 current_value_query (path, len, argv, argc, msg);
859                 ret = 0;
860
861         } else
862         if (!strncmp (path, "/cue/", 5)) {
863
864                 //cue_parse (path, types, argv, argc, msg)
865
866                 ret = 0;
867         } else
868         if (strcmp (path, "/strip/listen") == 0) {
869
870                 cerr << "set up listener\n";
871
872                 lo_message reply = lo_message_new ();
873
874                 if (argc <= 0) {
875                         lo_message_add_string (reply, "syntax error");
876                 } else {
877                         for (int n = 0; n < argc; ++n) {
878
879                                 boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
880
881                                 if (!r) {
882                                         lo_message_add_string (reply, "not found");
883                                         cerr << "no such route\n";
884                                         break;
885                                 } else {
886                                         cerr << "add listener\n";
887                                         listen_to_route (r, get_address (msg));
888                                         lo_message_add_int32 (reply, argv[n]->i);
889                                 }
890                         }
891                 }
892
893                 lo_send_message (get_address (msg), "#reply", reply);
894                 lo_message_free (reply);
895
896                 ret = 0;
897
898         } else
899         if (strcmp (path, "/strip/ignore") == 0) {
900
901                 for (int n = 0; n < argc; ++n) {
902
903                         boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
904
905                         if (r) {
906                                 end_listen (r, get_address (msg));
907                         }
908                 }
909
910                 ret = 0;
911         } else
912         if (!strncmp (path, "/strip/gain/", 12) && strlen (path) > 12) {
913                 // in dB
914                 int ssid = atoi (&path[12]);
915                 route_set_gain_dB (ssid, argv[0]->f, msg);
916                 ret = 0;
917         }
918         else if (!strncmp (path, "/strip/fader/", 13) && strlen (path) > 13) {
919                 // in fader position
920                 int ssid = atoi (&path[13]);
921                 route_set_gain_fader (ssid, argv[0]->f, msg);
922                 ret = 0;
923         }
924         else if (!strncmp (path, "/strip/trimdB/", 14) && strlen (path) > 14) {
925                 int ssid = atoi (&path[14]);
926                 route_set_trim_dB (ssid, argv[0]->f, msg);
927                 ret = 0;
928         }
929         else if (!strncmp (path, "/strip/pan_stereo_position/", 27) && strlen (path) > 27) {
930                 int ssid = atoi (&path[27]);
931                 route_set_pan_stereo_position (ssid, argv[0]->f, msg);
932                 ret = 0;
933         }
934         else if (!strncmp (path, "/strip/mute/", 12) && strlen (path) > 12) {
935                 int ssid = atoi (&path[12]);
936                 route_mute (ssid, argv[0]->i, msg);
937                 ret = 0;
938         }
939         else if (!strncmp (path, "/strip/solo/", 12) && strlen (path) > 12) {
940                 int ssid = atoi (&path[12]);
941                 route_solo (ssid, argv[0]->i, msg);
942                 ret = 0;
943         }
944         else if (!strncmp (path, "/strip/monitor_input/", 21) && strlen (path) > 21) {
945                 int ssid = atoi (&path[21]);
946                 route_monitor_input (ssid, argv[0]->i, msg);
947                 ret = 0;
948         }
949         else if (!strncmp (path, "/strip/monitor_disk/", 20) && strlen (path) > 20) {
950                 int ssid = atoi (&path[20]);
951                 route_monitor_disk (ssid, argv[0]->i, msg);
952                 ret = 0;
953         }
954         else if (!strncmp (path, "/strip/recenable/", 17) && strlen (path) > 17) {
955                 int ssid = atoi (&path[17]);
956                 route_recenable (ssid, argv[0]->i, msg);
957                 ret = 0;
958         }
959         else if (!strncmp (path, "/strip/record_safe/", 19) && strlen (path) > 19) {
960                 int ssid = atoi (&path[19]);
961                 route_recsafe (ssid, argv[0]->i, msg);
962                 ret = 0;
963         }
964         else if (!strncmp (path, "/strip/expand/", 14) && strlen (path) > 14) {
965                 int ssid = atoi (&path[14]);
966                 strip_expand (ssid, argv[0]->i, msg);
967                 ret = 0;
968         }
969         else if (!strncmp (path, "/strip/select/", 14) && strlen (path) > 14) {
970                 int ssid = atoi (&path[14]);
971                 strip_gui_select (ssid, argv[0]->i, msg);
972                 ret = 0;
973         }
974         else if (!strncmp (path, "/select/send_gain/", 18) && strlen (path) > 18) {
975                 int ssid = atoi (&path[18]);
976                 sel_sendgain (ssid, argv[0]->f, msg);
977                 ret = 0;
978         }
979         else if (!strncmp (path, "/select/send_fader/", 19) && strlen (path) > 19) {
980                 int ssid = atoi (&path[19]);
981                 sel_sendfader (ssid, argv[0]->f, msg);
982                 ret = 0;
983         }
984         else if (!strncmp (path, "/select/send_enable/", 20) && strlen (path) > 20) {
985                 int ssid = atoi (&path[20]);
986                 sel_sendenable (ssid, argv[0]->f, msg);
987                 ret = 0;
988         }
989         else if (!strncmp (path, "/select/eq_gain/", 16) && strlen (path) > 16) {
990                 int ssid = atoi (&path[16]);
991                 sel_eq_gain (ssid, argv[0]->f, msg);
992                 ret = 0;
993         }
994         else if (!strncmp (path, "/select/eq_freq/", 16) && strlen (path) > 16) {
995                 int ssid = atoi (&path[16]);
996                 sel_eq_freq (ssid, argv[0]->f , msg);
997                 ret = 0;
998         }
999         else if (!strncmp (path, "/select/eq_q/", 13) && strlen (path) > 13) {
1000                 int ssid = atoi (&path[13]);
1001                 sel_eq_q (ssid, argv[0]->f, msg);
1002                 ret = 0;
1003         }
1004         else if (!strncmp (path, "/select/eq_shape/", 17) && strlen (path) > 17) {
1005                 int ssid = atoi (&path[17]);
1006                 sel_eq_shape (ssid, argv[0]->f, msg);
1007                 ret = 0;
1008         }
1009
1010         if ((ret && _debugmode == Unhandled)) {
1011                 debugmsg (_("Unhandled OSC message"), path, types, argv, argc);
1012         } else if ((!ret && _debugmode == All)) {
1013                 debugmsg (_("OSC"), path, types, argv, argc);
1014         }
1015
1016         return ret;
1017 }
1018
1019 void
1020 OSC::debugmsg (const char *prefix, const char *path, const char* types, lo_arg **argv, int argc)
1021 {
1022         std::stringstream ss;
1023         for (int i = 0; i < argc; ++i) {
1024                 lo_type type = (lo_type)types[i];
1025                         ss << " ";
1026                 switch (type) {
1027                         case LO_INT32:
1028                                 ss << "i:" << argv[i]->i;
1029                                 break;
1030                         case LO_FLOAT:
1031                                 ss << "f:" << argv[i]->f;
1032                                 break;
1033                         case LO_DOUBLE:
1034                                 ss << "d:" << argv[i]->d;
1035                                 break;
1036                         case LO_STRING:
1037                                 ss << "s:" << &argv[i]->s;
1038                                 break;
1039                         case LO_INT64:
1040                                 ss << "h:" << argv[i]->h;
1041                                 break;
1042                         case LO_CHAR:
1043                                 ss << "c:" << argv[i]->s;
1044                                 break;
1045                         case LO_TIMETAG:
1046                                 ss << "<Timetag>";
1047                                 break;
1048                         case LO_BLOB:
1049                                 ss << "<BLOB>";
1050                                 break;
1051                         case LO_TRUE:
1052                                 ss << "#T";
1053                                 break;
1054                         case LO_FALSE:
1055                                 ss << "#F";
1056                                 break;
1057                         case LO_NIL:
1058                                 ss << "NIL";
1059                                 break;
1060                         case LO_INFINITUM:
1061                                 ss << "#inf";
1062                                 break;
1063                         case LO_MIDI:
1064                                 ss << "<MIDI>";
1065                                 break;
1066                         case LO_SYMBOL:
1067                                 ss << "<SYMBOL>";
1068                                 break;
1069                         default:
1070                                 ss << "< ?? >";
1071                                 break;
1072                 }
1073         }
1074         PBD::info << prefix << ": " << path << ss.str() << endmsg;
1075 }
1076
1077 void
1078 OSC::update_clock ()
1079 {
1080
1081 }
1082
1083 // "Application Hook" Handlers //
1084 void
1085 OSC::session_loaded (Session& s)
1086 {
1087 //      lo_address listener = lo_address_new (NULL, "7770");
1088 //      lo_send (listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str());
1089 }
1090
1091 void
1092 OSC::session_exported (std::string path, std::string name)
1093 {
1094         lo_address listener = lo_address_new (NULL, "7770");
1095         lo_send (listener, "/session/exported", "ss", path.c_str(), name.c_str());
1096         lo_address_free (listener);
1097 }
1098
1099 // end "Application Hook" Handlers //
1100
1101 /* path callbacks */
1102
1103 int
1104 OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, void */*data*/, void* /*user_data*/)
1105 {
1106 #if 0
1107         const char* returl;
1108
1109         if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != s) {
1110                 return 1;
1111         }
1112
1113         const char *returl = argv[1]->s;
1114         lo_address addr = find_or_cache_addr (returl);
1115
1116         const char *retpath = argv[2]->s;
1117
1118
1119         if (strcmp (argv[0]->s, "transport_frame") == 0) {
1120
1121                 if (session) {
1122                         lo_send (addr, retpath, "i", session->transport_frame());
1123                 }
1124
1125         } else if (strcmp (argv[0]->s, "transport_speed") == 0) {
1126
1127                 if (session) {
1128                         lo_send (addr, retpath, "i", session->transport_frame());
1129                 }
1130
1131         } else if (strcmp (argv[0]->s, "transport_locked") == 0) {
1132
1133                 if (session) {
1134                         lo_send (addr, retpath, "i", session->transport_frame());
1135                 }
1136
1137         } else if (strcmp (argv[0]->s, "punch_in") == 0) {
1138
1139                 if (session) {
1140                         lo_send (addr, retpath, "i", session->transport_frame());
1141                 }
1142
1143         } else if (strcmp (argv[0]->s, "punch_out") == 0) {
1144
1145                 if (session) {
1146                         lo_send (addr, retpath, "i", session->transport_frame());
1147                 }
1148
1149         } else if (strcmp (argv[0]->s, "rec_enable") == 0) {
1150
1151                 if (session) {
1152                         lo_send (addr, retpath, "i", session->transport_frame());
1153                 }
1154
1155         } else {
1156
1157                 /* error */
1158         }
1159 #endif
1160         return 0;
1161 }
1162
1163 void
1164 OSC::routes_list (lo_message msg)
1165 {
1166         if (!session) {
1167                 return;
1168         }
1169         for (int n = 0; n < (int) session->nroutes(); ++n) {
1170
1171                 boost::shared_ptr<Route> r = session->get_remote_nth_route (n);
1172
1173                 if (r) {
1174
1175                         lo_message reply = lo_message_new ();
1176
1177                         if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
1178                                 lo_message_add_string (reply, "AT");
1179                         } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
1180                                 lo_message_add_string (reply, "MT");
1181                         } else {
1182                                 lo_message_add_string (reply, "B");
1183                         }
1184
1185                         lo_message_add_string (reply, r->name().c_str());
1186                         lo_message_add_int32 (reply, r->n_inputs().n_audio());
1187                         lo_message_add_int32 (reply, r->n_outputs().n_audio());
1188                         lo_message_add_int32 (reply, r->muted());
1189                         lo_message_add_int32 (reply, r->soloed());
1190                         /* XXX Can only use order at this point */
1191                         //lo_message_add_int32 (reply, r->presentation_info().order());
1192                         // try this instead.
1193                         lo_message_add_int32 (reply, get_sid (r, get_address (msg)));
1194
1195                         if (boost::dynamic_pointer_cast<AudioTrack>(r)
1196                                         || boost::dynamic_pointer_cast<MidiTrack>(r)) {
1197
1198                                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
1199                                 lo_message_add_int32 (reply, (int32_t) t->rec_enable_control()->get_value());
1200                         }
1201
1202                         //Automatically listen to routes listed
1203                         listen_to_route(r, get_address (msg));
1204
1205                         lo_send_message (get_address (msg), "#reply", reply);
1206                         lo_message_free (reply);
1207                 }
1208         }
1209
1210         // Send end of listing message
1211         lo_message reply = lo_message_new ();
1212
1213         lo_message_add_string (reply, "end_route_list");
1214         lo_message_add_int64 (reply, session->frame_rate());
1215         lo_message_add_int64 (reply, session->current_end_frame());
1216
1217         lo_send_message (get_address (msg), "#reply", reply);
1218
1219         lo_message_free (reply);
1220 }
1221
1222 int
1223 OSC::cancel_all_solos ()
1224 {
1225         session->cancel_all_solo ();
1226         return 0;
1227 }
1228
1229 lo_address
1230 OSC::get_address (lo_message msg)
1231 {
1232         if (address_only) {
1233                 lo_address addr = lo_message_get_source (msg);
1234                 string host = lo_address_get_hostname (addr);
1235                 int protocol = lo_address_get_protocol (addr);
1236                 return lo_address_new_with_proto (protocol, host.c_str(), remote_port.c_str());
1237         } else {
1238                 return lo_message_get_source (msg);
1239         }
1240 }
1241
1242 int
1243 OSC::refresh_surface (lo_message msg)
1244 {
1245         if (address_only) {
1246                 // get rid of all surfaces and observers.
1247                 clear_devices();
1248         }
1249         OSCSurface *s = get_surface(get_address (msg));
1250         // restart all observers
1251         set_surface (s->bank_size, (uint32_t) s->strip_types.to_ulong(), (uint32_t) s->feedback.to_ulong(), (uint32_t) s->gainmode, msg);
1252         return 0;
1253 }
1254
1255 void
1256 OSC::clear_devices ()
1257 {
1258         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
1259
1260                 OSCRouteObserver* rc;
1261
1262                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
1263                         delete *x;
1264                         x = route_observers.erase (x);
1265                 } else {
1266                         ++x;
1267                 }
1268                 // slow devices need time to clear buffers
1269                 usleep ((uint32_t) 10);
1270         }
1271         // Should maybe do global_observers too
1272         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end();) {
1273
1274                 OSCGlobalObserver* gc;
1275
1276                 if ((gc = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
1277                         delete *x;
1278                         x = global_observers.erase (x);
1279                 } else {
1280                         ++x;
1281                 }
1282         }
1283         // delete select observers
1284         for (uint32_t it = 0; it < _surface.size(); ++it) {
1285                 OSCSurface* sur = &_surface[it];
1286                 OSCSelectObserver* so;
1287                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
1288                         delete so;
1289                 }
1290         }
1291         // clear out surfaces
1292         _surface.clear();
1293 }
1294
1295 int
1296 OSC::set_surface (uint32_t b_size, uint32_t strips, uint32_t fb, uint32_t gm, lo_message msg)
1297 {
1298         OSCSurface *s = get_surface(get_address (msg));
1299         s->bank_size = b_size;
1300         s->strip_types = strips;
1301         s->feedback = fb;
1302         s->gainmode = gm;
1303         // set bank and strip feedback
1304         set_bank(s->bank, msg);
1305
1306         global_feedback (s->feedback, get_address (msg), s->gainmode);
1307         return 0;
1308 }
1309
1310 int
1311 OSC::set_surface_bank_size (uint32_t bs, lo_message msg)
1312 {
1313         OSCSurface *s = get_surface(get_address (msg));
1314         s->bank_size = bs;
1315
1316         // set bank and strip feedback
1317         set_bank(s->bank, msg);
1318         return 0;
1319 }
1320
1321 int
1322 OSC::set_surface_strip_types (uint32_t st, lo_message msg)
1323 {
1324         OSCSurface *s = get_surface(get_address (msg));
1325         s->strip_types = st;
1326
1327         // set bank and strip feedback
1328         set_bank(s->bank, msg);
1329         return 0;
1330 }
1331
1332
1333 int
1334 OSC::set_surface_feedback (uint32_t fb, lo_message msg)
1335 {
1336         OSCSurface *s = get_surface(get_address (msg));
1337         s->feedback = fb;
1338
1339         // set bank and strip feedback
1340         set_bank(s->bank, msg);
1341
1342         // Set global/master feedback
1343         global_feedback (s->feedback, get_address (msg), s->gainmode);
1344         return 0;
1345 }
1346
1347
1348 int
1349 OSC::set_surface_gainmode (uint32_t gm, lo_message msg)
1350 {
1351         OSCSurface *s = get_surface(get_address (msg));
1352         s->gainmode = gm;
1353
1354         // set bank and strip feedback
1355         set_bank(s->bank, msg);
1356
1357         // Set global/master feedback
1358         global_feedback (s->feedback, get_address (msg), s->gainmode);
1359         return 0;
1360 }
1361
1362 OSC::OSCSurface *
1363 OSC::get_surface (lo_address addr)
1364 {
1365         string r_url;
1366         char * rurl;
1367         rurl = lo_address_get_url (addr);
1368         r_url = rurl;
1369         free (rurl);
1370         for (uint32_t it = 0; it < _surface.size(); ++it) {
1371                 //find setup for this server
1372                 if (!_surface[it].remote_url.find(r_url)){
1373                         return &_surface[it];
1374                 }
1375         }
1376         // if we do this when OSC is started we get the wrong stripable
1377         // we don't need this until we actually have a surface to deal with
1378         if (!_select || (_select != ControlProtocol::first_selected_stripable())) {
1379                 gui_selection_changed();
1380         }
1381
1382         // No surface create one with default values
1383         OSCSurface s;
1384         s.remote_url = r_url;
1385         s.bank = 1;
1386         s.bank_size = default_banksize; // need to find out how many strips there are
1387         s.strip_types = default_strip; // 159 is tracks, busses, and VCAs (no master/monitor)
1388         s.feedback = default_feedback;
1389         s.gainmode = default_gainmode;
1390         s.sel_obs = 0;
1391         s.expand = 0;
1392         s.expand_enable = false;
1393         s.strips = get_sorted_stripables(s.strip_types);
1394
1395         s.nstrips = s.strips.size();
1396         _surface.push_back (s);
1397
1398         return &_surface[_surface.size() - 1];
1399 }
1400
1401 // setup global feedback for a surface
1402 void
1403 OSC::global_feedback (bitset<32> feedback, lo_address addr, uint32_t gainmode)
1404 {
1405         // first destroy global observer for this surface
1406         GlobalObservers::iterator x;
1407         for (x = global_observers.begin(); x != global_observers.end();) {
1408
1409                 OSCGlobalObserver* ro;
1410
1411                 if ((ro = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
1412
1413                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
1414
1415                         if (res == 0) {
1416                                 delete *x;
1417                                 x = global_observers.erase (x);
1418                         } else {
1419                                 ++x;
1420                         }
1421                 } else {
1422                         ++x;
1423                 }
1424         }
1425         if (feedback[4] || feedback[3] || feedback[5] || feedback[6]) {
1426                 // create a new Global Observer for this surface
1427                 OSCGlobalObserver* o = new OSCGlobalObserver (*session, addr, gainmode, /*s->*/feedback);
1428                 global_observers.push_back (o);
1429         }
1430 }
1431
1432 void
1433 OSC::notify_routes_added (ARDOUR::RouteList &)
1434 {
1435         // not sure if we need this PI change seems to cover
1436         //recalcbanks();
1437 }
1438
1439 void
1440 OSC::notify_vca_added (ARDOUR::VCAList &)
1441 {
1442         // not sure if we need this PI change seems to cover
1443         //recalcbanks();
1444 }
1445
1446 void
1447 OSC::recalcbanks ()
1448 {
1449         tick = false;
1450         bank_dirty = true;
1451 }
1452
1453 void
1454 OSC::_recalcbanks ()
1455 {
1456         if (!_select || (_select != ControlProtocol::first_selected_stripable())) {
1457                 _select = ControlProtocol::first_selected_stripable();
1458         }
1459
1460         // do a set_bank for each surface we know about.
1461         for (uint32_t it = 0; it < _surface.size(); ++it) {
1462                 OSCSurface* sur = &_surface[it];
1463                 // find lo_address
1464                 lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
1465                 _set_bank (sur->bank, addr);
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         return true;
3496 }
3497
3498 int
3499 OSC::route_send_fail (string path, uint32_t ssid, float val, lo_address addr)
3500 {
3501         OSCSurface *sur = get_surface(addr);
3502
3503         ostringstream os;
3504         lo_message reply;
3505         if (ssid) {
3506                 reply = lo_message_new ();
3507                 if (sur->feedback[2]) {
3508                         os << "/strip/" << path << "/" << ssid;
3509                 } else {
3510                         os << "/strip/" << path;
3511                         lo_message_add_int32 (reply, ssid);
3512                 }
3513                 string str_pth = os.str();
3514                 lo_message_add_float (reply, (float) val);
3515
3516                 lo_send_message (addr, str_pth.c_str(), reply);
3517                 lo_message_free (reply);
3518         }
3519         if ((_select == get_strip (ssid, addr)) || ((sur->expand == ssid) && (sur->expand_enable))) {
3520                 os.str("");
3521                 os << "/select/" << path;
3522                 string sel_pth = os.str();
3523                 reply = lo_message_new ();
3524                 lo_message_add_float (reply, (float) val);
3525                 lo_send_message (addr, sel_pth.c_str(), reply);
3526                 lo_message_free (reply);
3527         }
3528
3529         return 0;
3530 }
3531
3532 int
3533 OSC::sel_fail (string path, float val, lo_address addr)
3534 {
3535         ostringstream os;
3536         os.str("");
3537         os << "/select/" << path;
3538         string sel_pth = os.str();
3539         lo_message reply = lo_message_new ();
3540         lo_message_add_float (reply, (float) val);
3541         lo_send_message (addr, sel_pth.c_str(), reply);
3542         lo_message_free (reply);
3543
3544         return 0;
3545 }
3546
3547 int
3548 OSC::sel_send_fail (string path, uint32_t id, float val, lo_address addr)
3549 {
3550         OSCSurface *sur = get_surface(addr);
3551
3552         ostringstream os;
3553         lo_message reply;
3554         reply = lo_message_new ();
3555         if (sur->feedback[2]) {
3556                 os << "/select/" << path << "/" << id;
3557         } else {
3558                 os << "/select/" << path;
3559                 lo_message_add_int32 (reply, id);
3560         }
3561         string str_pth = os.str();
3562         lo_message_add_float (reply, (float) val);
3563
3564         lo_send_message (addr, str_pth.c_str(), reply);
3565         lo_message_free (reply);
3566
3567         return 0;
3568 }
3569
3570 XMLNode&
3571 OSC::get_state ()
3572 {
3573         XMLNode& node (ControlProtocol::get_state());
3574         node.add_property("debugmode", (int) _debugmode); // TODO: enum2str
3575         node.add_property ("address-only", address_only);
3576         node.add_property ("remote-port", remote_port);
3577         node.add_property ("banksize", default_banksize);
3578         node.add_property ("striptypes", default_strip);
3579         node.add_property ("feedback", default_feedback);
3580         node.add_property ("gainmode", default_gainmode);
3581         if (_surface.size()) {
3582                 XMLNode* config = new XMLNode (X_("Configurations"));
3583                 for (uint32_t it = 0; it < _surface.size(); ++it) {
3584                         OSCSurface* sur = &_surface[it];
3585                         XMLNode* devnode = new XMLNode (X_("Configuration"));
3586                         devnode->add_property (X_("url"), sur->remote_url);
3587                         devnode->add_property (X_("bank-size"), sur->bank_size);
3588                         devnode->add_property (X_("strip-types"), sur->strip_types.to_ulong());
3589                         devnode->add_property (X_("feedback"), sur->feedback.to_ulong());
3590                         devnode->add_property (X_("gainmode"), sur->gainmode);
3591                         config->add_child_nocopy (*devnode);
3592                 }
3593                 node.add_child_nocopy (*config);
3594         }
3595         return node;
3596 }
3597
3598 int
3599 OSC::set_state (const XMLNode& node, int version)
3600 {
3601         if (ControlProtocol::set_state (node, version)) {
3602                 return -1;
3603         }
3604         XMLProperty const * p = node.property (X_("debugmode"));
3605         if (p) {
3606                 _debugmode = OSCDebugMode (PBD::atoi(p->value ()));
3607         }
3608         p = node.property (X_("address-only"));
3609         if (p) {
3610                 address_only = OSCDebugMode (PBD::atoi(p->value ()));
3611         }
3612         p = node.property (X_("remote-port"));
3613         if (p) {
3614                 remote_port = p->value ();
3615         }
3616         p = node.property (X_("banksize"));
3617         if (p) {
3618                 default_banksize = OSCDebugMode (PBD::atoi(p->value ()));
3619         }
3620         p = node.property (X_("striptypes"));
3621         if (p) {
3622                 default_strip = OSCDebugMode (PBD::atoi(p->value ()));
3623         }
3624         p = node.property (X_("feedback"));
3625         if (p) {
3626                 default_feedback = OSCDebugMode (PBD::atoi(p->value ()));
3627         }
3628         p = node.property (X_("gainmode"));
3629         if (p) {
3630                 default_gainmode = OSCDebugMode (PBD::atoi(p->value ()));
3631         }
3632         XMLNode* cnode = node.child (X_("Configurations"));
3633
3634         if (cnode) {
3635                 XMLNodeList const& devices = cnode->children();
3636                 for (XMLNodeList::const_iterator d = devices.begin(); d != devices.end(); ++d) {
3637                         XMLProperty const * prop = (*d)->property (X_("url"));
3638                         if (prop) {
3639                                 OSCSurface s;
3640                                 bank_dirty = true;
3641                                 s.remote_url = prop->value();
3642                                 prop = (*d)->property (X_("bank-size"));
3643                                 if (prop) {
3644                                         s.bank_size = atoi (prop->value().c_str());
3645                                 }
3646                                 prop = (*d)->property (X_("strip-types"));
3647                                 if (prop) {
3648                                         s.strip_types = atoi (prop->value().c_str());
3649                                 }
3650                                 prop = (*d)->property (X_("feedback"));
3651                                 if (prop) {
3652                                         s.feedback = atoi (prop->value().c_str());
3653                                 }
3654                                 prop = (*d)->property (X_("gainmode"));
3655                                 if (prop) {
3656                                         s.gainmode = atoi (prop->value().c_str());
3657                                 }
3658                                 s.bank = 1;
3659                                 s.sel_obs = 0;
3660                                 s.expand = 0;
3661                                 s.expand_enable = false;
3662                                 s.strips = get_sorted_stripables(s.strip_types);
3663                                 s.nstrips = s.strips.size();
3664                                 _surface.push_back (s);
3665                         }
3666                 }
3667         }
3668         global_init = true;
3669         tick = false;
3670
3671         return 0;
3672 }
3673
3674 // predicate for sort call in get_sorted_stripables
3675 struct StripableByPresentationOrder
3676 {
3677         bool operator () (const boost::shared_ptr<Stripable> & a, const boost::shared_ptr<Stripable> & b) const
3678         {
3679                 return a->presentation_info().order() < b->presentation_info().order();
3680         }
3681
3682         bool operator () (const Stripable & a, const Stripable & b) const
3683         {
3684                 return a.presentation_info().order() < b.presentation_info().order();
3685         }
3686
3687         bool operator () (const Stripable * a, const Stripable * b) const
3688         {
3689                 return a->presentation_info().order() < b->presentation_info().order();
3690         }
3691 };
3692
3693 OSC::Sorted
3694 OSC::get_sorted_stripables(std::bitset<32> types)
3695 {
3696         Sorted sorted;
3697
3698         // fetch all stripables
3699         StripableList stripables;
3700
3701         session->get_stripables (stripables);
3702
3703         // Look for stripables that match bit in sur->strip_types
3704         for (StripableList::iterator it = stripables.begin(); it != stripables.end(); ++it) {
3705
3706                 boost::shared_ptr<Stripable> s = *it;
3707                 if ((!types[9]) && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
3708                         // do nothing... skip it
3709                 } else {
3710
3711                         if (types[0] && (s->presentation_info().flags() & PresentationInfo::AudioTrack)) {
3712                                 sorted.push_back (s);
3713                         } else
3714                         if (types[1] && (s->presentation_info().flags() & PresentationInfo::MidiTrack)) {
3715                                 sorted.push_back (s);
3716                         } else
3717                         if ((s->presentation_info().flags() & PresentationInfo::AudioBus)) {
3718                                 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
3719                                 // r->feeds (session->master_out()) may make more sense
3720                                 if (r->direct_feeds_according_to_reality (session->master_out())) {
3721                                         // this is a bus
3722                                         if (types[2]) {
3723                                                 sorted.push_back (s);
3724                                         }
3725                                 } else {
3726                                         // this is an Aux out
3727                                         if (types[7]) {
3728                                                 sorted.push_back (s);
3729                                         }
3730                                 }
3731                         } else
3732                         if (types[3] && (s->presentation_info().flags() & PresentationInfo::MidiBus)) {
3733                                 sorted.push_back (s);
3734                         } else
3735                         if (types[4] && (s->presentation_info().flags() & PresentationInfo::VCA)) {
3736                                 sorted.push_back (s);
3737                         } else
3738                         if (types[8] && (s->presentation_info().flags() & PresentationInfo::Selected)) {
3739                                 sorted.push_back (s);
3740                         } else
3741                         if (types[9] && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
3742                                 sorted.push_back (s);
3743                         }
3744                 }
3745         }
3746         sort (sorted.begin(), sorted.end(), StripableByPresentationOrder());
3747         // Master/Monitor might be anywhere... we put them at the end - Sorry ;)
3748         if (types[5]) {
3749                 sorted.push_back (session->master_out());
3750         }
3751         if (types[6]) {
3752                 sorted.push_back (session->monitor_out());
3753         }
3754         return sorted;
3755 }
3756