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