68bea263f2d75fcb99b5dbdc7402af9d6b8be6df
[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/miscutils.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
51 #include "osc_select_observer.h"
52 #include "osc.h"
53 #include "osc_controllable.h"
54 #include "osc_route_observer.h"
55 #include "osc_global_observer.h"
56 #include "i18n.h"
57
58 using namespace ARDOUR;
59 using namespace std;
60 using namespace Glib;
61 using namespace ArdourSurface;
62
63 #include "pbd/abstract_ui.cc" // instantiate template
64
65 OSC* OSC::_instance = 0;
66
67 #ifdef DEBUG
68 static void error_callback(int num, const char *m, const char *path)
69 {
70         fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
71 }
72 #else
73 static void error_callback(int, const char *, const char *)
74 {
75
76 }
77 #endif
78
79 OSC::OSC (Session& s, uint32_t port)
80         : ControlProtocol (s, X_("Open Sound Control (OSC)"))
81         , AbstractUI<OSCUIRequest> (name())
82         , local_server (0)
83         , remote_server (0)
84         , _port(port)
85         , _ok (true)
86         , _shutdown (false)
87         , _osc_server (0)
88         , _osc_unix_server (0)
89         , _send_route_changes (true)
90         , _debugmode (Off)
91         , gui (0)
92 {
93         _instance = this;
94
95         session->Exported.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::session_exported, this, _1, _2), this);
96 }
97
98 OSC::~OSC()
99 {
100         stop ();
101         _instance = 0;
102 }
103
104 void*
105 OSC::request_factory (uint32_t num_requests)
106 {
107         /* AbstractUI<T>::request_buffer_factory() is a template method only
108            instantiated in this source module. To provide something visible for
109            use in the interface/descriptor, we have this static method that is
110            template-free.
111         */
112         return request_buffer_factory (num_requests);
113 }
114
115 void
116 OSC::do_request (OSCUIRequest* req)
117 {
118         if (req->type == CallSlot) {
119
120                 call_slot (MISSING_INVALIDATOR, req->the_slot);
121
122         } else if (req->type == Quit) {
123
124                 stop ();
125         }
126 }
127
128 int
129 OSC::set_active (bool yn)
130 {
131         if (yn != active()) {
132
133                 if (yn) {
134                         if (start ()) {
135                                 return -1;
136                         }
137                 } else {
138                         if (stop ()) {
139                                 return -1;
140                         }
141                 }
142
143         }
144
145         return ControlProtocol::set_active (yn);
146 }
147
148 bool
149 OSC::get_active () const
150 {
151         return _osc_server != 0;
152 }
153
154 int
155 OSC::set_feedback (bool yn)
156 {
157         _send_route_changes = yn;
158         return 0;
159 }
160
161 bool
162 OSC::get_feedback () const
163 {
164         return _send_route_changes;
165 }
166
167 int
168 OSC::start ()
169 {
170         char tmpstr[255];
171
172         if (_osc_server) {
173                 /* already started */
174                 return 0;
175         }
176
177         for (int j=0; j < 20; ++j) {
178                 snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
179
180                 //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
181                 //      break;
182                 //}
183
184                 if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
185                         break;
186                 }
187
188 #ifdef DEBUG
189                 cerr << "can't get osc at port: " << _port << endl;
190 #endif
191                 _port++;
192                 continue;
193         }
194
195         if (!_osc_server) {
196                 return 1;
197         }
198
199 #ifdef ARDOUR_OSC_UNIX_SERVER
200
201         // APPEARS sluggish for now
202
203         // attempt to create unix socket server too
204
205         snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
206         int fd = mkstemp(tmpstr);
207
208         if (fd >= 0 ) {
209                 ::g_unlink (tmpstr);
210                 close (fd);
211
212                 _osc_unix_server = lo_server_new (tmpstr, error_callback);
213
214                 if (_osc_unix_server) {
215                         _osc_unix_socket_path = tmpstr;
216                 }
217         }
218 #endif
219
220         PBD::info << "OSC @ " << get_server_url () << endmsg;
221
222         std::string url_file;
223
224         if (find_file (ardour_config_search_path(), "osc_url", url_file)) {
225                 _osc_url_file = url_file;
226                 if (g_file_set_contents (_osc_url_file.c_str(), get_server_url().c_str(), -1, NULL)) {
227                         cerr << "Couldn't write '" <<  _osc_url_file << "'" <<endl;
228                 }
229         }
230
231         register_callbacks();
232
233         session_loaded (*session);
234
235         // lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
236
237         /* startup the event loop thread */
238
239         BaseUI::run ();
240
241         // start timers for metering, timecode and heartbeat.
242         // timecode and metering run at 100
243         Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
244         periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &OSC::periodic));
245         periodic_timeout->attach (main_loop()->get_context());
246
247         StripableSelectionChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::gui_selection_changed, this, _1), this);
248
249         return 0;
250 }
251
252 void
253 OSC::thread_init ()
254 {
255         pthread_set_name (event_loop_name().c_str());
256
257         if (_osc_unix_server) {
258                 Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
259                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_unix_server));
260                 src->attach (_main_loop->get_context());
261                 local_server = src->gobj();
262                 g_source_ref (local_server);
263         }
264
265         if (_osc_server) {
266 #ifdef PLATFORM_WINDOWS
267                 Glib::RefPtr<IOChannel> chan = Glib::IOChannel::create_from_win32_socket (lo_server_get_socket_fd (_osc_server));
268                 Glib::RefPtr<IOSource> src  = IOSource::create (chan, IO_IN|IO_HUP|IO_ERR);
269 #else
270                 Glib::RefPtr<IOSource> src  = IOSource::create (lo_server_get_socket_fd (_osc_server), IO_IN|IO_HUP|IO_ERR);
271 #endif
272                 src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_server));
273                 src->attach (_main_loop->get_context());
274                 remote_server = src->gobj();
275                 g_source_ref (remote_server);
276         }
277
278         PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
279         SessionEvent::create_per_thread_pool (event_loop_name(), 128);
280 }
281
282 int
283 OSC::stop ()
284 {
285         /* stop main loop */
286
287         if (local_server) {
288                 g_source_destroy (local_server);
289                 g_source_unref (local_server);
290                 local_server = 0;
291         }
292
293         if (remote_server) {
294                 g_source_destroy (remote_server);
295                 g_source_unref (remote_server);
296                 remote_server = 0;
297         }
298
299         BaseUI::quit ();
300
301         if (_osc_server) {
302                 lo_server_free (_osc_server);
303                 _osc_server = 0;
304         }
305
306         if (_osc_unix_server) {
307                 lo_server_free (_osc_unix_server);
308                 _osc_unix_server = 0;
309         }
310
311         if (!_osc_unix_socket_path.empty()) {
312                 ::g_unlink (_osc_unix_socket_path.c_str());
313         }
314
315         if (!_osc_url_file.empty() ) {
316                 ::g_unlink (_osc_url_file.c_str() );
317         }
318
319         periodic_connection.disconnect ();
320         session_connections.drop_connections ();
321         // Delete any active route observers
322         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
323
324                 OSCRouteObserver* rc;
325
326                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
327                         delete *x;
328                         x = route_observers.erase (x);
329                 } else {
330                         ++x;
331                 }
332         }
333 // Should maybe do global_observers too
334         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end();) {
335
336                 OSCGlobalObserver* gc;
337
338                 if ((gc = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
339                         delete *x;
340                         x = global_observers.erase (x);
341                 } else {
342                         ++x;
343                 }
344         }
345 // delete select observers
346         for (uint32_t it = 0; it < _surface.size(); ++it) {
347                 OSCSurface* sur = &_surface[it];
348                 OSCSelectObserver* so;
349                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
350                         delete so;
351                 }
352         }
353
354         return 0;
355 }
356
357 void
358 OSC::register_callbacks()
359 {
360         lo_server srvs[2];
361         lo_server serv;
362
363         srvs[0] = _osc_server;
364         srvs[1] = _osc_unix_server;
365
366         for (size_t i = 0; i < 2; ++i) {
367
368                 if (!srvs[i]) {
369                         continue;
370                 }
371
372                 serv = srvs[i];
373
374
375 #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this)
376
377                 // Some controls have optional "f" for feedback or touchosc
378                 // http://hexler.net/docs/touchosc-controls-reference
379
380                 REGISTER_CALLBACK (serv, "/set_surface", "iiii", set_surface);
381                 REGISTER_CALLBACK (serv, "/set_surface/feedback", "i", set_surface_feedback);
382                 REGISTER_CALLBACK (serv, "/set_surface/bank_size", "i", set_surface_bank_size);
383                 REGISTER_CALLBACK (serv, "/set_surface/gainmode", "i", set_surface_gainmode);
384                 REGISTER_CALLBACK (serv, "/set_surface/strip_types", "i", set_surface_strip_types);
385                 REGISTER_CALLBACK (serv, "/strip/list", "", routes_list);
386                 REGISTER_CALLBACK (serv, "/add_marker", "", add_marker);
387                 REGISTER_CALLBACK (serv, "/add_marker", "f", add_marker);
388                 REGISTER_CALLBACK (serv, "/access_action", "s", access_action);
389                 REGISTER_CALLBACK (serv, "/loop_toggle", "", loop_toggle);
390                 REGISTER_CALLBACK (serv, "/loop_toggle", "f", loop_toggle);
391                 REGISTER_CALLBACK (serv, "/loop_location", "ii", loop_location);
392                 REGISTER_CALLBACK (serv, "/goto_start", "", goto_start);
393                 REGISTER_CALLBACK (serv, "/goto_start", "f", goto_start);
394                 REGISTER_CALLBACK (serv, "/goto_end", "", goto_end);
395                 REGISTER_CALLBACK (serv, "/goto_end", "f", goto_end);
396                 REGISTER_CALLBACK (serv, "/rewind", "", rewind);
397                 REGISTER_CALLBACK (serv, "/rewind", "f", rewind);
398                 REGISTER_CALLBACK (serv, "/ffwd", "", ffwd);
399                 REGISTER_CALLBACK (serv, "/ffwd", "f", ffwd);
400                 REGISTER_CALLBACK (serv, "/transport_stop", "", transport_stop);
401                 REGISTER_CALLBACK (serv, "/transport_stop", "f", transport_stop);
402                 REGISTER_CALLBACK (serv, "/transport_play", "", transport_play);
403                 REGISTER_CALLBACK (serv, "/transport_play", "f", transport_play);
404                 REGISTER_CALLBACK (serv, "/transport_frame", "", transport_frame);
405                 REGISTER_CALLBACK (serv, "/transport_speed", "", transport_speed);
406                 REGISTER_CALLBACK (serv, "/record_enabled", "", record_enabled);
407                 REGISTER_CALLBACK (serv, "/set_transport_speed", "f", set_transport_speed);
408                 // locate ii is position and bool roll
409                 REGISTER_CALLBACK (serv, "/locate", "ii", locate);
410                 REGISTER_CALLBACK (serv, "/save_state", "", save_state);
411                 REGISTER_CALLBACK (serv, "/save_state", "f", save_state);
412                 REGISTER_CALLBACK (serv, "/prev_marker", "", prev_marker);
413                 REGISTER_CALLBACK (serv, "/prev_marker", "f", prev_marker);
414                 REGISTER_CALLBACK (serv, "/next_marker", "", next_marker);
415                 REGISTER_CALLBACK (serv, "/next_marker", "f", next_marker);
416                 REGISTER_CALLBACK (serv, "/undo", "", undo);
417                 REGISTER_CALLBACK (serv, "/undo", "f", undo);
418                 REGISTER_CALLBACK (serv, "/redo", "", redo);
419                 REGISTER_CALLBACK (serv, "/redo", "f", redo);
420                 REGISTER_CALLBACK (serv, "/toggle_punch_in", "", toggle_punch_in);
421                 REGISTER_CALLBACK (serv, "/toggle_punch_in", "f", toggle_punch_in);
422                 REGISTER_CALLBACK (serv, "/toggle_punch_out", "", toggle_punch_out);
423                 REGISTER_CALLBACK (serv, "/toggle_punch_out", "f", toggle_punch_out);
424                 REGISTER_CALLBACK (serv, "/rec_enable_toggle", "", rec_enable_toggle);
425                 REGISTER_CALLBACK (serv, "/rec_enable_toggle", "f", rec_enable_toggle);
426                 REGISTER_CALLBACK (serv, "/toggle_all_rec_enables", "", toggle_all_rec_enables);
427                 REGISTER_CALLBACK (serv, "/toggle_all_rec_enables", "f", toggle_all_rec_enables);
428                 REGISTER_CALLBACK (serv, "/all_tracks_rec_in", "f", all_tracks_rec_in);
429                 REGISTER_CALLBACK (serv, "/all_tracks_rec_out", "f", all_tracks_rec_out);
430                 REGISTER_CALLBACK (serv, "/remove_marker", "", remove_marker_at_playhead);
431                 REGISTER_CALLBACK (serv, "/remove_marker", "f", remove_marker_at_playhead);
432                 REGISTER_CALLBACK (serv, "/jump_bars", "f", jump_by_bars);
433                 REGISTER_CALLBACK (serv, "/jump_seconds", "f", jump_by_seconds);
434                 REGISTER_CALLBACK (serv, "/mark_in", "", mark_in);
435                 REGISTER_CALLBACK (serv, "/mark_in", "f", mark_in);
436                 REGISTER_CALLBACK (serv, "/mark_out", "", mark_out);
437                 REGISTER_CALLBACK (serv, "/mark_out", "f", mark_out);
438                 REGISTER_CALLBACK (serv, "/toggle_click", "", toggle_click);
439                 REGISTER_CALLBACK (serv, "/toggle_click", "f", toggle_click);
440                 REGISTER_CALLBACK (serv, "/midi_panic", "", midi_panic);
441                 REGISTER_CALLBACK (serv, "/midi_panic", "f", midi_panic);
442                 REGISTER_CALLBACK (serv, "/toggle_roll", "", toggle_roll);
443                 REGISTER_CALLBACK (serv, "/toggle_roll", "f", toggle_roll);
444                 REGISTER_CALLBACK (serv, "/stop_forget", "", stop_forget);
445                 REGISTER_CALLBACK (serv, "/stop_forget", "f", stop_forget);
446                 REGISTER_CALLBACK (serv, "/set_punch_range", "", set_punch_range);
447                 REGISTER_CALLBACK (serv, "/set_punch_range", "f", set_punch_range);
448                 REGISTER_CALLBACK (serv, "/set_loop_range", "", set_loop_range);
449                 REGISTER_CALLBACK (serv, "/set_loop_range", "f", set_loop_range);
450                 REGISTER_CALLBACK (serv, "/set_session_range", "", set_session_range);
451                 REGISTER_CALLBACK (serv, "/set_session_range", "f", set_session_range);
452                 // /toggle_monitor_* not working (comented out)
453                 REGISTER_CALLBACK (serv, "/toggle_monitor_mute", "", toggle_monitor_mute);
454                 REGISTER_CALLBACK (serv, "/toggle_monitor_mute", "f", toggle_monitor_mute);
455                 REGISTER_CALLBACK (serv, "/toggle_monitor_dim", "", toggle_monitor_dim);
456                 REGISTER_CALLBACK (serv, "/toggle_monitor_dim", "f", toggle_monitor_dim);
457                 REGISTER_CALLBACK (serv, "/toggle_monitor_mono", "", toggle_monitor_mono);
458                 REGISTER_CALLBACK (serv, "/toggle_monitor_mono", "f", toggle_monitor_mono);
459                 REGISTER_CALLBACK (serv, "/quick_snapshot_switch", "", quick_snapshot_switch);
460                 REGISTER_CALLBACK (serv, "/quick_snapshot_switch", "f", quick_snapshot_switch);
461                 REGISTER_CALLBACK (serv, "/quick_snapshot_stay", "", quick_snapshot_stay);
462                 REGISTER_CALLBACK (serv, "/quick_snapshot_stay", "f", quick_snapshot_stay);
463                 REGISTER_CALLBACK (serv, "/fit_1_track", "", fit_1_track);
464                 REGISTER_CALLBACK (serv, "/fit_1_track", "f", fit_1_track);
465                 REGISTER_CALLBACK (serv, "/fit_2_tracks", "", fit_2_tracks);
466                 REGISTER_CALLBACK (serv, "/fit_2_tracks", "f", fit_2_tracks);
467                 REGISTER_CALLBACK (serv, "/fit_4_tracks", "", fit_4_tracks);
468                 REGISTER_CALLBACK (serv, "/fit_4_tracks", "f", fit_4_tracks);
469                 REGISTER_CALLBACK (serv, "/fit_8_tracks", "", fit_8_tracks);
470                 REGISTER_CALLBACK (serv, "/fit_8_tracks", "f", fit_8_tracks);
471                 REGISTER_CALLBACK (serv, "/fit_16_tracks", "", fit_16_tracks);
472                 REGISTER_CALLBACK (serv, "/fit_16_tracks", "f", fit_16_tracks);
473                 REGISTER_CALLBACK (serv, "/fit_32_tracks", "", fit_32_tracks);
474                 REGISTER_CALLBACK (serv, "/fit_32_tracks", "f", fit_32_tracks);
475                 REGISTER_CALLBACK (serv, "/fit_all_tracks", "", fit_all_tracks);
476                 REGISTER_CALLBACK (serv, "/fit_all_tracks", "f", fit_all_tracks);
477                 REGISTER_CALLBACK (serv, "/zoom_100_ms", "", zoom_100_ms);
478                 REGISTER_CALLBACK (serv, "/zoom_100_ms", "f", zoom_100_ms);
479                 REGISTER_CALLBACK (serv, "/zoom_1_sec", "", zoom_1_sec);
480                 REGISTER_CALLBACK (serv, "/zoom_1_sec", "f", zoom_1_sec);
481                 REGISTER_CALLBACK (serv, "/zoom_10_sec", "", zoom_10_sec);
482                 REGISTER_CALLBACK (serv, "/zoom_10_sec", "f", zoom_10_sec);
483                 REGISTER_CALLBACK (serv, "/zoom_1_min", "", zoom_1_min);
484                 REGISTER_CALLBACK (serv, "/zoom_1_min", "f", zoom_1_min);
485                 REGISTER_CALLBACK (serv, "/zoom_5_min", "", zoom_5_min);
486                 REGISTER_CALLBACK (serv, "/zoom_5_min", "f", zoom_5_min);
487                 REGISTER_CALLBACK (serv, "/zoom_10_min", "", zoom_10_min);
488                 REGISTER_CALLBACK (serv, "/zoom_10_min", "f", zoom_10_min);
489                 REGISTER_CALLBACK (serv, "/zoom_to_session", "", zoom_to_session);
490                 REGISTER_CALLBACK (serv, "/zoom_to_session", "f", zoom_to_session);
491                 REGISTER_CALLBACK (serv, "/temporal_zoom_in", "f", temporal_zoom_in);
492                 REGISTER_CALLBACK (serv, "/temporal_zoom_in", "", temporal_zoom_in);
493                 REGISTER_CALLBACK (serv, "/temporal_zoom_out", "", temporal_zoom_out);
494                 REGISTER_CALLBACK (serv, "/temporal_zoom_out", "f", temporal_zoom_out);
495                 REGISTER_CALLBACK (serv, "/scroll_up_1_track", "f", scroll_up_1_track);
496                 REGISTER_CALLBACK (serv, "/scroll_up_1_track", "", scroll_up_1_track);
497                 REGISTER_CALLBACK (serv, "/scroll_dn_1_track", "f", scroll_dn_1_track);
498                 REGISTER_CALLBACK (serv, "/scroll_dn_1_track", "", scroll_dn_1_track);
499                 REGISTER_CALLBACK (serv, "/scroll_up_1_page", "f", scroll_up_1_page);
500                 REGISTER_CALLBACK (serv, "/scroll_up_1_page", "", scroll_up_1_page);
501                 REGISTER_CALLBACK (serv, "/scroll_dn_1_page", "f", scroll_dn_1_page);
502                 REGISTER_CALLBACK (serv, "/scroll_dn_1_page", "", scroll_dn_1_page);
503                 REGISTER_CALLBACK (serv, "/bank_up", "", bank_up);
504                 REGISTER_CALLBACK (serv, "/bank_up", "f", bank_up);
505                 REGISTER_CALLBACK (serv, "/bank_down", "", bank_down);
506                 REGISTER_CALLBACK (serv, "/bank_down", "f", bank_down);
507
508                 // controls for "special" strips
509                 REGISTER_CALLBACK (serv, "/master/gain", "f", master_set_gain);
510                 REGISTER_CALLBACK (serv, "/master/fader", "i", master_set_fader);
511                 REGISTER_CALLBACK (serv, "/master/mute", "i", master_set_mute);
512                 REGISTER_CALLBACK (serv, "/master/trimdB", "f", master_set_trim);
513                 REGISTER_CALLBACK (serv, "/master/pan_stereo_position", "f", master_set_pan_stereo_position);
514                 REGISTER_CALLBACK (serv, "/monitor/gain", "f", monitor_set_gain);
515                 REGISTER_CALLBACK (serv, "/monitor/fader", "i", monitor_set_fader);
516
517                 // Controls for the Selected strip
518                 REGISTER_CALLBACK (serv, "/select/recenable", "i", sel_recenable);
519                 REGISTER_CALLBACK (serv, "/select/record_safe", "i", sel_recsafe);
520                 REGISTER_CALLBACK (serv, "/select/mute", "i", sel_mute);
521                 REGISTER_CALLBACK (serv, "/select/solo", "i", sel_solo);
522                 REGISTER_CALLBACK (serv, "/select/monitor_input", "i", sel_monitor_input);
523                 REGISTER_CALLBACK (serv, "/select/monitor_disk", "i", sel_monitor_disk);
524                 REGISTER_CALLBACK (serv, "/select/gain", "f", sel_gain);
525                 REGISTER_CALLBACK (serv, "/select/fader", "f", sel_fader);
526                 REGISTER_CALLBACK (serv, "/select/trimdB", "f", sel_trim);
527                 REGISTER_CALLBACK (serv, "/select/pan_stereo_position", "f", sel_pan_position);
528                 REGISTER_CALLBACK (serv, "/select/pan_stereo_width", "f", sel_pan_width);
529
530                 REGISTER_CALLBACK (serv, "/select/phase", "i", sel_phase);
531
532                 /* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these  */ 
533                 REGISTER_CALLBACK (serv, "/strip/mute", "ii", route_mute);
534                 REGISTER_CALLBACK (serv, "/strip/solo", "ii", route_solo);
535                 REGISTER_CALLBACK (serv, "/strip/recenable", "ii", route_recenable);
536                 REGISTER_CALLBACK (serv, "/strip/record_safe", "ii", route_recsafe);
537                 REGISTER_CALLBACK (serv, "/strip/monitor_input", "ii", route_monitor_input);
538                 REGISTER_CALLBACK (serv, "/strip/monitor_disk", "ii", route_monitor_disk);
539                 REGISTER_CALLBACK (serv, "/strip/select", "ii", strip_select);
540                 REGISTER_CALLBACK (serv, "/strip/gui_select", "ii", strip_gui_select);
541                 REGISTER_CALLBACK (serv, "/strip/phase", "ii", strip_phase);
542                 REGISTER_CALLBACK (serv, "/strip/gain", "if", route_set_gain_dB);
543                 REGISTER_CALLBACK (serv, "/strip/fader", "if", route_set_gain_fader);
544                 REGISTER_CALLBACK (serv, "/strip/trimabs", "if", route_set_trim_abs);
545                 REGISTER_CALLBACK (serv, "/strip/trimdB", "if", route_set_trim_dB);
546                 REGISTER_CALLBACK (serv, "/strip/pan_stereo_position", "if", route_set_pan_stereo_position);
547                 REGISTER_CALLBACK (serv, "/strip/pan_stereo_width", "if", route_set_pan_stereo_width);
548                 REGISTER_CALLBACK (serv, "/strip/plugin/parameter", "iiif", route_plugin_parameter);
549                 // prints to cerr only
550                 REGISTER_CALLBACK (serv, "/strip/plugin/parameter/print", "iii", route_plugin_parameter_print);
551                 REGISTER_CALLBACK (serv, "/strip/send/gainabs", "iif", route_set_send_gain_abs);
552                 REGISTER_CALLBACK (serv, "/strip/send/gain", "iif", route_set_send_gain_dB);
553                 REGISTER_CALLBACK (serv, "/strip/send/fader", "iif", route_set_send_fader);
554
555                 /* still not-really-standardized query interface */
556                 //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
557                 //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
558
559                 // un/register_update args= s:ctrl s:returl s:retpath
560                 //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
561                 //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
562                 //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
563                 //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
564
565                 /* this is a special catchall handler,
566                  * register at the end so this is only called if no
567                  * other handler matches (used for debug) */
568                 lo_server_add_method (serv, 0, 0, _catchall, this);
569         }
570 }
571
572 bool
573 OSC::osc_input_handler (IOCondition ioc, lo_server srv)
574 {
575         if (ioc & ~IO_IN) {
576                 return false;
577         }
578
579         if (ioc & IO_IN) {
580                 lo_server_recv (srv);
581         }
582
583         return true;
584 }
585
586 std::string
587 OSC::get_server_url()
588 {
589         string url;
590         char * urlstr;
591
592         if (_osc_server) {
593                 urlstr = lo_server_get_url (_osc_server);
594                 url = urlstr;
595                 free (urlstr);
596         }
597
598         return url;
599 }
600
601 std::string
602 OSC::get_unix_server_url()
603 {
604         string url;
605         char * urlstr;
606
607         if (_osc_unix_server) {
608                 urlstr = lo_server_get_url (_osc_unix_server);
609                 url = urlstr;
610                 free (urlstr);
611         }
612
613         return url;
614 }
615
616 void
617 OSC::listen_to_route (boost::shared_ptr<Stripable> strip, lo_address addr)
618 {
619         /* avoid duplicate listens */
620
621         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); ++x) {
622
623                 OSCRouteObserver* ro;
624
625                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
626
627                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(addr));
628
629                         if (ro->strip() == strip && res == 0) {
630                                 return;
631                         }
632                 }
633         }
634
635         OSCSurface *s = get_surface(addr);
636         uint32_t sid = get_sid (strip->presentation_info().order() + 1, addr);
637         // above is zero based add 1
638         OSCRouteObserver* o = new OSCRouteObserver (strip, addr, sid, s->gainmode, s->feedback);
639         route_observers.push_back (o);
640
641         strip->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr<Stripable> (strip)), this);
642 }
643
644 void
645 OSC::drop_route (boost::weak_ptr<Stripable> wr)
646 {
647         boost::shared_ptr<Stripable> r = wr.lock ();
648
649         if (!r) {
650                 return;
651         }
652
653         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
654
655                 OSCRouteObserver* rc;
656
657                 if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
658
659                         if (rc->strip() == r) {
660                                 delete *x;
661                                 x = route_observers.erase (x);
662                         } else {
663                                 ++x;
664                         }
665                 } else {
666                         ++x;
667                 }
668         }
669 }
670
671 void
672 OSC::end_listen (boost::shared_ptr<Stripable> r, lo_address addr)
673 {
674         RouteObservers::iterator x;
675
676         // Remove the route observers
677         for (x = route_observers.begin(); x != route_observers.end();) {
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() == r && res == 0) {
686                                 delete *x;
687                                 x = route_observers.erase (x);
688                         }
689                         else {
690                                 ++x;
691                         }
692                 }
693                 else {
694                         ++x;
695                 }
696         }
697 }
698
699 void
700 OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg)
701 {
702         char* subpath;
703
704         subpath = (char*) malloc (len-15+1);
705         memcpy (subpath, path, len-15);
706         subpath[len-15] = '\0';
707
708         send_current_value (subpath, argv, argc, msg);
709
710         free (subpath);
711 }
712
713 void
714 OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg)
715 {
716         if (!session) {
717                 return;
718         }
719
720         lo_message reply = lo_message_new ();
721         boost::shared_ptr<Route> r;
722         int id;
723
724         lo_message_add_string (reply, path);
725
726         if (argc == 0) {
727                 lo_message_add_string (reply, "bad syntax");
728         } else {
729                 id = argv[0]->i;
730                 r = session->get_remote_nth_route (id);
731
732                 if (!r) {
733                         lo_message_add_string (reply, "not found");
734                 } else {
735
736                         if (strcmp (path, "/strip/state") == 0) {
737
738                                 if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
739                                         lo_message_add_string (reply, "AT");
740                                 } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
741                                         lo_message_add_string (reply, "MT");
742                                 } else {
743                                         lo_message_add_string (reply, "B");
744                                 }
745
746                                 lo_message_add_string (reply, r->name().c_str());
747                                 lo_message_add_int32 (reply, r->n_inputs().n_audio());
748                                 lo_message_add_int32 (reply, r->n_outputs().n_audio());
749                                 lo_message_add_int32 (reply, r->muted());
750                                 lo_message_add_int32 (reply, r->soloed());
751
752                         } else if (strcmp (path, "/strip/mute") == 0) {
753
754                                 lo_message_add_int32 (reply, (float) r->muted());
755
756                         } else if (strcmp (path, "/strip/solo") == 0) {
757
758                                 lo_message_add_int32 (reply, r->soloed());
759                         }
760                 }
761         }
762
763         lo_send_message (lo_message_get_source (msg), "#reply", reply);
764         lo_message_free (reply);
765 }
766
767 int
768 OSC::_catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data)
769 {
770         return ((OSC*)user_data)->catchall (path, types, argv, argc, data);
771 }
772
773 int
774 OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_message msg)
775 {
776         size_t len;
777         int ret = 1; /* unhandled */
778
779         //cerr << "Received a message, path = " << path << " types = \""
780         //     << (types ? types : "NULL") << '"' << endl;
781
782         /* 15 for /#current_value plus 2 for /<path> */
783
784         len = strlen (path);
785
786         if (len >= 17 && !strcmp (&path[len-15], "/#current_value")) {
787                 current_value_query (path, len, argv, argc, msg);
788                 ret = 0;
789
790         } else if (strcmp (path, "/strip/listen") == 0) {
791
792                 cerr << "set up listener\n";
793
794                 lo_message reply = lo_message_new ();
795
796                 if (argc <= 0) {
797                         lo_message_add_string (reply, "syntax error");
798                 } else {
799                         for (int n = 0; n < argc; ++n) {
800
801                                 boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
802
803                                 if (!r) {
804                                         lo_message_add_string (reply, "not found");
805                                         cerr << "no such route\n";
806                                         break;
807                                 } else {
808                                         cerr << "add listener\n";
809                                         listen_to_route (r, lo_message_get_source (msg));
810                                         lo_message_add_int32 (reply, argv[n]->i);
811                                 }
812                         }
813                 }
814
815                 lo_send_message (lo_message_get_source (msg), "#reply", reply);
816                 lo_message_free (reply);
817
818                 ret = 0;
819
820         } else if (strcmp (path, "/strip/ignore") == 0) {
821
822                 for (int n = 0; n < argc; ++n) {
823
824                         boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
825
826                         if (r) {
827                                 end_listen (r, lo_message_get_source (msg));
828                         }
829                 }
830
831                 ret = 0;
832         } else if (argc == 1 && types[0] == 'f') { // single float -- probably TouchOSC
833                 if (!strncmp (path, "/strip/gain/", 12) && strlen (path) > 12) {
834                         // in dB
835                         int ssid = atoi (&path[12]);
836                         route_set_gain_dB (ssid, argv[0]->f, msg);
837                         ret = 0;
838                 }
839                 else if (!strncmp (path, "/strip/fader/", 13) && strlen (path) > 13) {
840                         // in fader position
841                         int ssid = atoi (&path[13]);
842                         route_set_gain_fader (ssid, argv[0]->f, msg);
843                         ret = 0;
844                 }
845                 else if (!strncmp (path, "/strip/trimdB/", 14) && strlen (path) > 14) {
846                         int ssid = atoi (&path[14]);
847                         route_set_trim_dB (ssid, argv[0]->f, msg);
848                         ret = 0;
849                 }
850                 else if (!strncmp (path, "/strip/mute/", 12) && strlen (path) > 12) {
851                         int ssid = atoi (&path[12]);
852                         route_mute (ssid, argv[0]->f == 1.0, msg);
853                         ret = 0;
854                 }
855                 else if (!strncmp (path, "/strip/solo/", 12) && strlen (path) > 12) {
856                         int ssid = atoi (&path[12]);
857                         route_solo (ssid, argv[0]->f == 1.0, msg);
858                         ret = 0;
859                 }
860                 else if (!strncmp (path, "/strip/monitor_input/", 21) && strlen (path) > 21) {
861                         int ssid = atoi (&path[21]);
862                         route_monitor_input (ssid, argv[0]->f == 1.0, msg);
863                         ret = 0;
864                 }
865                 else if (!strncmp (path, "/strip/monitor_disk/", 20) && strlen (path) > 20) {
866                         int ssid = atoi (&path[20]);
867                         route_monitor_disk (ssid, argv[0]->f == 1.0, msg);
868                         ret = 0;
869                 }
870                 else if (!strncmp (path, "/strip/recenable/", 17) && strlen (path) > 17) {
871                         int ssid = atoi (&path[17]);
872                         route_recenable (ssid, argv[0]->f == 1.0, msg);
873                         ret = 0;
874                 }
875                 else if (!strncmp (path, "/strip/record_safe/", 19) && strlen (path) > 19) {
876                         int ssid = atoi (&path[19]);
877                         route_recsafe (ssid, argv[0]->f == 1.0, msg);
878                         ret = 0;
879                 }
880                 else if (!strncmp (path, "/strip/select/", 14) && strlen (path) > 14) {
881                         int ssid = atoi (&path[14]);
882                         strip_select (ssid, argv[0]->f == 1.0, msg);
883                         ret = 0;
884                 }
885                 else if (!strncmp (path, "/strip/gui_select/", 18) && strlen (path) > 18) {
886                         int ssid = atoi (&path[18]);
887                         strip_gui_select (ssid, argv[0]->f == 1.0, msg);
888                         ret = 0;
889                 }
890         }
891
892         if ((ret && _debugmode == Unhandled)) {
893                 debugmsg (_("Unhandled OSC message"), path, types, argv, argc);
894         }
895
896         return ret;
897 }
898
899 void
900 OSC::debugmsg (const char *prefix, const char *path, const char* types, lo_arg **argv, int argc)
901 {
902         std::stringstream ss;
903         for (int i = 0; i < argc; ++i) {
904                 lo_type type = (lo_type)types[i];
905                         ss << " ";
906                 switch (type) {
907                         case LO_INT32:
908                                 ss << "i:" << argv[i]->i;
909                                 break;
910                         case LO_FLOAT:
911                                 ss << "f:" << argv[i]->f;
912                                 break;
913                         case LO_DOUBLE:
914                                 ss << "d:" << argv[i]->d;
915                                 break;
916                         case LO_STRING:
917                                 ss << "s:" << &argv[i]->s;
918                                 break;
919                         case LO_INT64:
920                                 ss << "h:" << argv[i]->h;
921                                 break;
922                         case LO_CHAR:
923                                 ss << "c:" << argv[i]->s;
924                                 break;
925                         case LO_TIMETAG:
926                                 ss << "<Timetag>";
927                                 break;
928                         case LO_BLOB:
929                                 ss << "<BLOB>";
930                                 break;
931                         case LO_TRUE:
932                                 ss << "#T";
933                                 break;
934                         case LO_FALSE:
935                                 ss << "#F";
936                                 break;
937                         case LO_NIL:
938                                 ss << "NIL";
939                                 break;
940                         case LO_INFINITUM:
941                                 ss << "#inf";
942                                 break;
943                         case LO_MIDI:
944                                 ss << "<MIDI>";
945                                 break;
946                         case LO_SYMBOL:
947                                 ss << "<SYMBOL>";
948                                 break;
949                         default:
950                                 ss << "< ?? >";
951                                 break;
952                 }
953         }
954         PBD::info << prefix << ": " << path << ss.str() << endmsg;
955 }
956
957 void
958 OSC::update_clock ()
959 {
960
961 }
962
963 // "Application Hook" Handlers //
964 void
965 OSC::session_loaded (Session& s)
966 {
967 //      lo_address listener = lo_address_new (NULL, "7770");
968 //      lo_send (listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str());
969 }
970
971 void
972 OSC::session_exported (std::string path, std::string name)
973 {
974         lo_address listener = lo_address_new (NULL, "7770");
975         lo_send (listener, "/session/exported", "ss", path.c_str(), name.c_str());
976         lo_address_free (listener);
977 }
978
979 // end "Application Hook" Handlers //
980
981 /* path callbacks */
982
983 int
984 OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, void */*data*/, void* /*user_data*/)
985 {
986 #if 0
987         const char* returl;
988
989         if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != s) {
990                 return 1;
991         }
992
993         const char *returl = argv[1]->s;
994         lo_address addr = find_or_cache_addr (returl);
995
996         const char *retpath = argv[2]->s;
997
998
999         if (strcmp (argv[0]->s, "transport_frame") == 0) {
1000
1001                 if (session) {
1002                         lo_send (addr, retpath, "i", session->transport_frame());
1003                 }
1004
1005         } else if (strcmp (argv[0]->s, "transport_speed") == 0) {
1006
1007                 if (session) {
1008                         lo_send (addr, retpath, "i", session->transport_frame());
1009                 }
1010
1011         } else if (strcmp (argv[0]->s, "transport_locked") == 0) {
1012
1013                 if (session) {
1014                         lo_send (addr, retpath, "i", session->transport_frame());
1015                 }
1016
1017         } else if (strcmp (argv[0]->s, "punch_in") == 0) {
1018
1019                 if (session) {
1020                         lo_send (addr, retpath, "i", session->transport_frame());
1021                 }
1022
1023         } else if (strcmp (argv[0]->s, "punch_out") == 0) {
1024
1025                 if (session) {
1026                         lo_send (addr, retpath, "i", session->transport_frame());
1027                 }
1028
1029         } else if (strcmp (argv[0]->s, "rec_enable") == 0) {
1030
1031                 if (session) {
1032                         lo_send (addr, retpath, "i", session->transport_frame());
1033                 }
1034
1035         } else {
1036
1037                 /* error */
1038         }
1039 #endif
1040         return 0;
1041 }
1042
1043 void
1044 OSC::routes_list (lo_message msg)
1045 {
1046         if (!session) {
1047                 return;
1048         }
1049         for (int n = 0; n < (int) session->nroutes(); ++n) {
1050
1051                 boost::shared_ptr<Route> r = session->get_remote_nth_route (n);
1052
1053                 if (r) {
1054
1055                         lo_message reply = lo_message_new ();
1056
1057                         if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
1058                                 lo_message_add_string (reply, "AT");
1059                         } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
1060                                 lo_message_add_string (reply, "MT");
1061                         } else {
1062                                 lo_message_add_string (reply, "B");
1063                         }
1064
1065                         lo_message_add_string (reply, r->name().c_str());
1066                         lo_message_add_int32 (reply, r->n_inputs().n_audio());
1067                         lo_message_add_int32 (reply, r->n_outputs().n_audio());
1068                         lo_message_add_int32 (reply, r->muted());
1069                         lo_message_add_int32 (reply, r->soloed());
1070                         /* XXX Can only use order at this point */
1071                         lo_message_add_int32 (reply, r->presentation_info().order());
1072
1073                         if (boost::dynamic_pointer_cast<AudioTrack>(r)
1074                                         || boost::dynamic_pointer_cast<MidiTrack>(r)) {
1075
1076                                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
1077                                 lo_message_add_int32 (reply, (int32_t) t->rec_enable_control()->get_value());
1078                         }
1079
1080                         //Automatically listen to routes listed
1081                         listen_to_route(r, lo_message_get_source (msg));
1082
1083                         lo_send_message (lo_message_get_source (msg), "#reply", reply);
1084                         lo_message_free (reply);
1085                 }
1086         }
1087
1088         // Send end of listing message
1089         lo_message reply = lo_message_new ();
1090
1091         lo_message_add_string (reply, "end_route_list");
1092         lo_message_add_int64 (reply, session->frame_rate());
1093         lo_message_add_int64 (reply, session->current_end_frame());
1094
1095         lo_send_message (lo_message_get_source (msg), "#reply", reply);
1096
1097         lo_message_free (reply);
1098 }
1099
1100 int
1101 OSC::set_surface (uint32_t b_size, uint32_t strips, uint32_t fb, uint32_t gm, lo_message msg)
1102 {
1103         OSCSurface *s = get_surface(lo_message_get_source (msg));
1104         s->bank_size = b_size;
1105         s->strip_types = strips;
1106         //next line could be a call that finds out how many strips there are
1107         s->nstrips = session->nroutes(); // need to do this for strips
1108         s->feedback = fb;
1109         s->gainmode = gm;
1110         // set bank and strip feedback
1111         set_bank(s->bank, msg);
1112
1113         global_feedback (s->feedback, msg, s->gainmode);
1114         return 0;
1115 }
1116
1117 int
1118 OSC::set_surface_bank_size (uint32_t bs, lo_message msg)
1119 {
1120         OSCSurface *s = get_surface(lo_message_get_source (msg));
1121         s->bank_size = bs;
1122
1123         // set bank and strip feedback
1124         set_bank(s->bank, msg);
1125         return 0;
1126 }
1127
1128
1129 int
1130 OSC::set_surface_strip_types (uint32_t st, lo_message msg)
1131 {
1132         OSCSurface *s = get_surface(lo_message_get_source (msg));
1133         s->strip_types = st;
1134         //next line could be a call that finds out how many strips there are
1135         s->nstrips = session->nroutes(); // need to do this for strips
1136
1137         // set bank and strip feedback
1138         set_bank(s->bank, msg);
1139         return 0;
1140 }
1141
1142
1143 int
1144 OSC::set_surface_feedback (uint32_t fb, lo_message msg)
1145 {
1146         OSCSurface *s = get_surface(lo_message_get_source (msg));
1147         s->feedback = fb;
1148
1149         // set bank and strip feedback
1150         set_bank(s->bank, msg);
1151
1152         // Set global/master feedback
1153         global_feedback (s->feedback, msg, s->gainmode);
1154         return 0;
1155 }
1156
1157
1158 int
1159 OSC::set_surface_gainmode (uint32_t gm, lo_message msg)
1160 {
1161         OSCSurface *s = get_surface(lo_message_get_source (msg));
1162         s->gainmode = gm;
1163
1164         // set bank and strip feedback
1165         set_bank(s->bank, msg);
1166
1167         // Set global/master feedback
1168         global_feedback (s->feedback, msg, s->gainmode);
1169         return 0;
1170 }
1171
1172 OSC::OSCSurface *
1173 OSC::get_surface (lo_address addr)
1174 {
1175         string r_url;
1176         char * rurl;
1177         rurl = lo_address_get_url (addr);
1178         r_url = rurl;
1179         free (rurl);
1180         for (uint32_t it = 0; it < _surface.size(); ++it) {
1181                 //find setup for this server
1182                 if (!_surface[it].remote_url.find(r_url)){
1183                         return &_surface[it];
1184                 }
1185         }
1186         // No surface create one with default values
1187         OSCSurface s;
1188         s.remote_url = r_url;
1189         s.bank = 1;
1190         s.bank_size = 0; // need to find out how many strips there are
1191         s.nstrips = session->nroutes(); // may need to do this after MARK below
1192         s.strip_types = 31; // 31 is tracks, busses, and VCAs (no master/monitor)
1193         s.feedback = 0;
1194         s.gainmode = 0;
1195         s.sel_obs = 0;
1196         s.surface_sel = 0;
1197         //get sorted should go here
1198         _surface.push_back (s);
1199         //MARK
1200         return &_surface[_surface.size() - 1];
1201 }
1202
1203 // setup global feedback for a surface
1204 void
1205 OSC::global_feedback (bitset<32> feedback, lo_address msg, uint32_t gainmode)
1206 {
1207         // first destroy global observer for this surface
1208         GlobalObservers::iterator x;
1209
1210         for (x = global_observers.begin(); x != global_observers.end();) {
1211
1212                 OSCGlobalObserver* ro;
1213
1214                 if ((ro = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
1215
1216                         int res = strcmp(lo_address_get_url(ro->address()), lo_address_get_url(lo_message_get_source (msg)));
1217
1218                         if (res == 0) {
1219                                 delete *x;
1220                                 x = global_observers.erase (x);
1221                         } else {
1222                                 ++x;
1223                         }
1224                 } else {
1225                         ++x;
1226                 }
1227         }
1228         if (feedback[4] || feedback[3] || feedback[5] || feedback[6]) {
1229                 // create a new Global Observer for this surface
1230                 //OSCSurface *s = get_surface (lo_message_get_source (msg));
1231                 OSCGlobalObserver* o = new OSCGlobalObserver (*session, lo_message_get_source (msg), gainmode, /*s->*/feedback);
1232                 global_observers.push_back (o);
1233         }
1234 }
1235
1236 /*
1237  * This gets called not only when bank changes but also:
1238  *  - bank size change
1239  *  - feedback change
1240  *  - strip types changes
1241  *  - fadermode changes
1242  *  - stripable creation/deletion/flag
1243  *  - to refresh what is "displayed"
1244  * Basically any time the bank needs to be rebuilt
1245  */
1246 int
1247 OSC::set_bank (uint32_t bank_start, lo_message msg)
1248 {
1249         if (!session) {
1250                 return -1;
1251         }
1252         //StripableList strips;
1253         //session->get_stripables (strips);
1254         // no nstripables yet
1255         if (!session->nroutes()) {
1256                 return -1;
1257         }
1258         // don't include monitor or master in count for now
1259         uint32_t nstrips;
1260         if (session->monitor_out ()) {
1261                 nstrips = session->nroutes() - 2;
1262         } else {
1263                 nstrips = session->nroutes() - 1;
1264         }
1265         // reset local select
1266         _strip_select (0, lo_message_get_source (msg));
1267         // undo all listeners for this url
1268         for (int n = 0; n <= (int) nstrips; ++n) {
1269
1270                 boost::shared_ptr<Stripable> stp = session->get_remote_nth_stripable (n, PresentationInfo::Route);
1271
1272                 if (stp) {
1273                         end_listen (stp, lo_message_get_source (msg));
1274                 }
1275         }
1276
1277         OSCSurface *s = get_surface (lo_message_get_source (msg));
1278         uint32_t b_size;
1279
1280         if (!s->bank_size) {
1281                 // no banking
1282                 b_size = nstrips;
1283         } else {
1284                 b_size = s->bank_size;
1285         }
1286
1287         // Do limits checking - high end still not quite right
1288         if (bank_start < 1) bank_start = 1;
1289         if (b_size >= nstrips)  {
1290                 bank_start = 1;
1291         } else if ((bank_start > nstrips)) {
1292                 bank_start = (uint32_t)((nstrips - b_size) + 1);
1293         }
1294         //save bank in case we have had to change it
1295         s->bank = bank_start;
1296
1297         if (s->feedback[0] || s->feedback[1]) {
1298                 for (int n = bank_start; n < (int) (b_size + bank_start); ++n) {
1299                         // this next will eventually include strip types
1300                         boost::shared_ptr<Stripable> stp = session->get_remote_nth_stripable (n - 1, PresentationInfo::Route);
1301
1302                         if (stp) {
1303                                 listen_to_route(stp, lo_message_get_source (msg));
1304                                 if (!s->feedback[10]) {
1305                                         if (stp->is_selected()) {
1306                                                 _strip_select (n, lo_message_get_source (msg));
1307                                         }
1308                                 }
1309                         }
1310                 }
1311         }
1312         return 0;
1313 }
1314
1315 int
1316 OSC::bank_up (lo_message msg)
1317 {
1318         if (!session) {
1319                 return -1;
1320         }
1321         OSCSurface *s = get_surface(lo_message_get_source (msg));
1322         set_bank (s->bank + s->bank_size, msg);
1323         return 0;
1324 }
1325
1326 int
1327 OSC::bank_down (lo_message msg)
1328 {
1329         if (!session) {
1330                 return -1;
1331         }
1332         OSCSurface *s = get_surface(lo_message_get_source (msg));
1333         if (s->bank < s->bank_size) {
1334                 set_bank (1, msg);
1335         } else {
1336                 set_bank (s->bank - s->bank_size, msg);
1337         }
1338         return 0;
1339 }
1340
1341 uint32_t
1342 OSC::get_sid (uint32_t rid, lo_address addr)
1343 {
1344         OSCSurface *s = get_surface(addr);
1345         return rid - s->bank + 1;
1346 }
1347
1348 uint32_t
1349 OSC::get_rid (uint32_t ssid, lo_address addr)
1350 {
1351         OSCSurface *s = get_surface(addr);
1352         return ssid + s->bank - 2;
1353 }
1354
1355 void
1356 OSC::transport_frame (lo_message msg)
1357 {
1358         if (!session) {
1359                 return;
1360         }
1361         framepos_t pos = session->transport_frame ();
1362
1363         lo_message reply = lo_message_new ();
1364         lo_message_add_int64 (reply, pos);
1365
1366         lo_send_message (lo_message_get_source (msg), "/transport_frame", reply);
1367
1368         lo_message_free (reply);
1369 }
1370
1371 void
1372 OSC::transport_speed (lo_message msg)
1373 {
1374         if (!session) {
1375                 return;
1376         }
1377         double ts = session->transport_speed ();
1378
1379         lo_message reply = lo_message_new ();
1380         lo_message_add_double (reply, ts);
1381
1382         lo_send_message (lo_message_get_source (msg), "/transport_speed", reply);
1383
1384         lo_message_free (reply);
1385 }
1386
1387 void
1388 OSC::record_enabled (lo_message msg)
1389 {
1390         if (!session) {
1391                 return;
1392         }
1393         int re = (int)session->get_record_enabled ();
1394
1395         lo_message reply = lo_message_new ();
1396         lo_message_add_int32 (reply, re);
1397
1398         lo_send_message (lo_message_get_source (msg), "/record_enabled", reply);
1399
1400         lo_message_free (reply);
1401 }
1402
1403 // master and monitor calls
1404 int
1405 OSC::master_set_gain (float dB)
1406 {
1407         if (!session) return -1;
1408         boost::shared_ptr<Stripable> s = session->master_out();
1409         if (s) {
1410                 if (dB < -192) {
1411                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
1412                 } else {
1413                         s->gain_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1414                 }
1415         }
1416         return 0;
1417 }
1418
1419 int
1420 OSC::master_set_fader (uint32_t position)
1421 {
1422         if (!session) return -1;
1423         boost::shared_ptr<Stripable> s = session->master_out();
1424         if (s) {
1425                 if ((position > 799.5) && (position < 800.5)) {
1426                         s->gain_control()->set_value (1.0, PBD::Controllable::NoGroup);
1427                 } else {
1428                         s->gain_control()->set_value (slider_position_to_gain_with_max (((float)position/1023), 2.0), PBD::Controllable::NoGroup);
1429                 }
1430         }
1431         return 0;
1432 }
1433
1434 int
1435 OSC::master_set_trim (float dB)
1436 {
1437         if (!session) return -1;
1438         boost::shared_ptr<Stripable> s = session->master_out();
1439
1440         if (s) {
1441                 s->trim_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1442         }
1443
1444         return 0;
1445 }
1446
1447 int
1448 OSC::master_set_pan_stereo_position (float position)
1449 {
1450         if (!session) return -1;
1451
1452         boost::shared_ptr<Stripable> s = session->master_out();
1453
1454         if (s) {
1455                 if (s->pan_azimuth_control()) {
1456                         s->pan_azimuth_control()->set_value (position, PBD::Controllable::NoGroup);
1457                 }
1458         }
1459
1460         return 0;
1461 }
1462
1463 int
1464 OSC::master_set_mute (uint32_t state)
1465 {
1466         if (!session) return -1;
1467
1468         boost::shared_ptr<Stripable> s = session->master_out();
1469
1470         if (s) {
1471                 s->mute_control()->set_value (state, PBD::Controllable::NoGroup);
1472         }
1473
1474         return 0;
1475 }
1476
1477 int
1478 OSC::monitor_set_gain (float dB)
1479 {
1480         if (!session) return -1;
1481         boost::shared_ptr<Stripable> s = session->monitor_out();
1482
1483         if (s) {
1484                 if (dB < -192) {
1485                         s->gain_control()->set_value (0.0, PBD::Controllable::NoGroup);
1486                 } else {
1487                         s->gain_control()->set_value (dB_to_coefficient (dB), PBD::Controllable::NoGroup);
1488                 }
1489         }
1490         return 0;
1491 }
1492
1493 int
1494 OSC::monitor_set_fader (uint32_t position)
1495 {
1496         if (!session) return -1;
1497         boost::shared_ptr<Stripable> s = session->monitor_out();
1498         if (s) {
1499                 if ((position > 799.5) && (position < 800.5)) {
1500                         s->gain_control()->set_value (1.0, PBD::Controllable::NoGroup);
1501                 } else {
1502                         s->gain_control()->set_value (slider_position_to_gain_with_max (((float)position/1023), 2.0), PBD::Controllable::NoGroup);
1503                 }
1504         }
1505         return 0;
1506 }
1507
1508 // strip calls
1509 int
1510 OSC::route_mute (int ssid, int yn, lo_message msg)
1511 {
1512         if (!session) return -1;
1513         int rid = get_rid (ssid, lo_message_get_source (msg));
1514
1515         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1516
1517         if (s) {
1518                 s->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1519         }
1520
1521         return 0;
1522 }
1523
1524 int
1525 OSC::sel_mute (uint32_t yn, lo_message msg)
1526 {
1527         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1528         if (sur->surface_sel) {
1529                 return route_mute(sur->surface_sel, yn, msg);
1530         } else { 
1531                 return route_send_fail ("mute", 0, 0, lo_message_get_source (msg));
1532         }
1533 }
1534
1535 int
1536 OSC::route_solo (int ssid, int yn, lo_message msg)
1537 {
1538         if (!session) return -1;
1539         int rid = get_rid (ssid, lo_message_get_source (msg));
1540
1541         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1542
1543         if (s) {
1544                 s->solo_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1545         }
1546
1547         return 0;
1548 }
1549
1550 int
1551 OSC::sel_solo (uint32_t yn, lo_message msg)
1552 {
1553         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1554         if (sur->surface_sel) {
1555                 return route_solo(sur->surface_sel, yn, msg);
1556         } else { 
1557                 return route_send_fail ("solo", 0, 0, lo_message_get_source (msg));
1558         }
1559 }
1560
1561 int
1562 OSC::sel_recenable (uint32_t yn, lo_message msg)
1563 {
1564         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1565         if (sur->surface_sel) {
1566                 return route_recenable(sur->surface_sel, yn, msg);
1567         } else { 
1568                 return route_send_fail ("recenable", 0, 0, lo_message_get_source (msg));
1569         }
1570 }
1571
1572 int
1573 OSC::route_recenable (int ssid, int yn, lo_message msg)
1574 {
1575         if (!session) return -1;
1576         int rid = get_rid (ssid, lo_message_get_source (msg));
1577
1578         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1579
1580         if (s) {
1581                 if (s->rec_enable_control()) {
1582                         s->rec_enable_control()->set_value (yn, PBD::Controllable::UseGroup);
1583                         if (s->rec_enable_control()->get_value()) {
1584                                 return 0;
1585                         }
1586                 }
1587         }
1588         // hmm, not set for whatever reason tell surface
1589         return route_send_fail ("recenable", ssid, 0, lo_message_get_source (msg));
1590 }
1591
1592 int
1593 OSC::sel_recsafe (uint32_t yn, lo_message msg)
1594 {
1595         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1596         if (sur->surface_sel) {
1597                 return route_recsafe(sur->surface_sel, yn, msg);
1598         } else { 
1599                 return route_send_fail ("record_safe", 0, 0, lo_message_get_source (msg));
1600         }
1601 }
1602
1603 int
1604 OSC::route_recsafe (int ssid, int yn, lo_message msg)
1605 {
1606         if (!session) return -1;
1607         int rid = get_rid (ssid, lo_message_get_source (msg));
1608
1609         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1610         if (s) {
1611                 if (s->rec_safe_control()) {
1612                         s->rec_safe_control()->set_value (yn, PBD::Controllable::UseGroup);
1613                         if (s->rec_safe_control()->get_value()) {
1614                                 return 0;
1615                         }
1616                 }
1617         }
1618         // hmm, not set for whatever reason tell surface
1619         return route_send_fail ("record_safe", ssid, 0,lo_message_get_source (msg));
1620 }
1621
1622 int
1623 OSC::route_monitor_input (int ssid, int yn, lo_message msg)
1624 {
1625         if (!session) return -1;
1626         int rid = get_rid (ssid, lo_message_get_source (msg));
1627
1628         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1629
1630         if (s) {
1631                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
1632                 if (track) {
1633                         track->monitoring_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1634                 } else {
1635                         route_send_fail ("monitor_input", ssid, 0, lo_message_get_source (msg));
1636                 }
1637         }
1638
1639         return 0;
1640 }
1641
1642 int
1643 OSC::sel_monitor_input (uint32_t yn, lo_message msg)
1644 {
1645         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1646         if (sur->surface_sel) {
1647                 return route_monitor_input(sur->surface_sel, yn, msg);
1648         } else { 
1649                 return route_send_fail ("monitor_input", 0, 0, lo_message_get_source (msg));
1650         }
1651 }
1652
1653 int
1654 OSC::route_monitor_disk (int ssid, int yn, lo_message msg)
1655 {
1656         if (!session) return -1;
1657         int rid = get_rid (ssid, lo_message_get_source (msg));
1658
1659         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1660
1661         if (s) {
1662                 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (s);
1663                 if (track) {
1664                         track->monitoring_control()->set_value (yn ? 2.0 : 0.0, PBD::Controllable::NoGroup);
1665                 } else {
1666                         route_send_fail ("monitor_disk", ssid, 0, lo_message_get_source (msg));
1667                 }
1668         }
1669
1670         return 0;
1671 }
1672
1673 int
1674 OSC::sel_monitor_disk (uint32_t yn, lo_message msg)
1675 {
1676         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1677         if (sur->surface_sel) {
1678                 return route_monitor_disk(sur->surface_sel, yn, msg);
1679         } else { 
1680                 return route_send_fail ("monitor_disk", 0, 0, lo_message_get_source (msg));
1681         }
1682 }
1683
1684
1685 int
1686 OSC::strip_phase (int ssid, int yn, lo_message msg)
1687 {
1688         if (!session) return -1;
1689         int rid = get_rid (ssid, lo_message_get_source (msg));
1690
1691         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1692
1693         if (s) {
1694                 s->phase_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
1695         }
1696
1697         return 0;
1698 }
1699
1700 int
1701 OSC::sel_phase (uint32_t yn, lo_message msg)
1702 {
1703         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1704         if (sur->surface_sel) {
1705                 return strip_phase(sur->surface_sel, yn, msg);
1706         } else { 
1707                 return route_send_fail ("phase", 0, 0, lo_message_get_source (msg));
1708         }
1709 }
1710
1711 int
1712 OSC::strip_select (int ssid, int yn, lo_message msg)
1713 {
1714         //ignore button release
1715         if (!yn) return 0;
1716
1717         return _strip_select ( ssid, lo_message_get_source (msg));
1718 }
1719
1720 int
1721 OSC::_strip_select (int ssid, lo_address addr)
1722 {
1723         if (!session) {
1724                 route_send_fail ("select", ssid, 0, addr);
1725                 return -1;
1726         }
1727         int rid = get_rid (ssid, addr);
1728         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1729         OSCSurface *sur = get_surface(addr);
1730         if (sur->sel_obs) {
1731                 delete sur->sel_obs;
1732                 sur->sel_obs = 0;
1733         }
1734         sur->surface_sel = 0;
1735
1736         if (s) {
1737                 sur->surface_sel = ssid;
1738                 OSCSelectObserver* sel_fb = new OSCSelectObserver (s, addr, ssid, sur->gainmode, sur->feedback);
1739                 sur->sel_obs = sel_fb;
1740         } else {
1741                 route_send_fail ("select", ssid, 0 , addr);
1742         }
1743         int b_s = sur->bank_size;
1744         if (!b_s) { // bank size 0 means we need to know how many strips there are.
1745                 b_s = sur->nstrips;
1746         }
1747         for (int i = 1;  i <= b_s; i++) {
1748                 string path = "select";
1749                 if (!sur->feedback[10]) {
1750                         path = "gui_select";
1751                 }
1752                 if (i==(int)sur->surface_sel) {
1753                         lo_message reply = lo_message_new ();
1754                         if (sur->feedback[2]) {
1755                                 ostringstream os;
1756                                 os << "/strip/" << path << "/" << ssid;
1757                                 path = os.str();
1758                         } else {
1759                                 ostringstream os;
1760                                 os << "/strip/" << path;
1761                                 path = os.str();
1762                                 lo_message_add_int32 (reply, ssid);
1763                         }
1764                                 lo_message_add_float (reply, (float) 1);
1765
1766                                 lo_send_message (addr, path.c_str(), reply);
1767                                 lo_message_free (reply);
1768                         } else {
1769                                 route_send_fail (path, i, 0, addr);
1770                         }
1771         }
1772
1773         return 0;
1774 }
1775
1776 int
1777 OSC::strip_gui_select (int ssid, int yn, lo_message msg)
1778 {
1779         //ignore button release
1780         if (!yn) return 0;
1781
1782         if (!session) {
1783                 route_send_fail ("gui_select", ssid, 0, lo_message_get_source (msg));
1784                 return -1;
1785         }
1786
1787         int rid = get_rid (ssid, lo_message_get_source (msg));
1788         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1789         if (s) {
1790         //SetStripableSelection ((*s)->presentation_info().order());
1791                 SetStripableSelection (rid); //alt above may end up being better
1792         } else {
1793                 route_send_fail ("gui_select", ssid, 0, lo_message_get_source (msg));
1794         }
1795
1796         return 0;
1797 }
1798
1799 int
1800 OSC::route_set_gain_abs (int rid, float level, lo_message msg)
1801 {
1802         if (!session) return -1;
1803         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1804
1805         if (s) {
1806                 s->gain_control()->set_value (level, PBD::Controllable::NoGroup);
1807         }
1808
1809         return 0;
1810 }
1811
1812 int
1813 OSC::route_set_gain_dB (int ssid, float dB, lo_message msg)
1814 {
1815         if (!session) {
1816                 route_send_fail ("gain", ssid, -193, lo_message_get_source (msg));
1817                 return -1;
1818         }
1819         int ret;
1820         int rid = get_rid (ssid, lo_message_get_source (msg));
1821         if (dB < -192) {
1822                 ret = route_set_gain_abs (rid, 0.0, msg);
1823         } else {
1824                 ret = route_set_gain_abs (rid, dB_to_coefficient (dB), msg);
1825         }
1826         if (ret != 0) {
1827                 route_send_fail ("gain", ssid, -193, lo_message_get_source (msg));
1828         }
1829         return ret;
1830 }
1831
1832 int
1833 OSC::sel_gain (float val, lo_message msg)
1834 {
1835         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1836         if (sur->surface_sel) {
1837                 return route_set_gain_dB(sur->surface_sel, val, msg);
1838         } else { 
1839                 return route_send_fail ("gain", 0, -193, lo_message_get_source (msg));
1840         }
1841 }
1842
1843 int
1844 OSC::route_set_gain_fader (int ssid, float pos, lo_message msg)
1845 {
1846         if (!session) {
1847                 route_send_fail ("fader", ssid, 0, lo_message_get_source (msg));
1848                 return -1;
1849         }
1850         int ret;
1851         int rid = get_rid (ssid, lo_message_get_source (msg));
1852         if ((pos > 799.5) && (pos < 800.5)) {
1853                 ret = route_set_gain_abs (rid, 1.0, msg);
1854         } else {
1855                 ret = route_set_gain_abs (rid, slider_position_to_gain_with_max ((pos/1023), 2.0), msg);
1856         }
1857         if (ret != 0) {
1858                 route_send_fail ("fader", ssid, 0, lo_message_get_source (msg));
1859         }
1860         return ret;
1861 }
1862
1863 int
1864 OSC::sel_fader (float val, lo_message msg)
1865 {
1866         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1867         if (sur->surface_sel) {
1868                 return route_set_gain_fader(sur->surface_sel, val, msg);
1869         } else { 
1870                 return route_send_fail ("fader", 0, 0, lo_message_get_source (msg));
1871         }
1872 }
1873
1874 int
1875 OSC::route_set_trim_abs (int ssid, float level, lo_message msg)
1876 {
1877         if (!session) return -1;
1878         int rid = get_rid (ssid, lo_message_get_source (msg));
1879
1880         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1881
1882         if (s) {
1883                 if (s->trim_control()) {
1884                         s->trim_control()->set_value (level, PBD::Controllable::NoGroup);
1885                 }
1886
1887         }
1888
1889         return 0;
1890 }
1891
1892 int
1893 OSC::route_set_trim_dB (int ssid, float dB, lo_message msg)
1894 {
1895         return route_set_trim_abs(ssid, dB_to_coefficient (dB), msg);
1896 }
1897
1898 int
1899 OSC::sel_trim (float val, lo_message msg)
1900 {
1901         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1902         if (sur->surface_sel) {
1903                 return route_set_trim_dB (sur->surface_sel, val, msg);
1904         } else { 
1905                 return route_send_fail ("trimdB", 0, 0, lo_message_get_source (msg));
1906         }
1907 }
1908
1909 int
1910 OSC::sel_pan_position (float val, lo_message msg)
1911 {
1912         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1913         if (sur->surface_sel) {
1914                 return route_set_pan_stereo_position (sur->surface_sel, val, msg);
1915         } else { 
1916                 return route_send_fail ("pan_stereo_position", 0, 0.5, lo_message_get_source (msg));
1917         }
1918 }
1919
1920 int
1921 OSC::sel_pan_width (float val, lo_message msg)
1922 {
1923         OSCSurface *sur = get_surface(lo_message_get_source (msg));
1924         if (sur->surface_sel) {
1925                 return route_set_pan_stereo_width (sur->surface_sel, val, msg);
1926         } else { 
1927                 return route_send_fail ("pan_stereo_width", 0, 1, lo_message_get_source (msg));
1928         }
1929 }
1930
1931 int
1932 OSC::route_set_pan_stereo_position (int ssid, float pos, lo_message msg)
1933 {
1934         if (!session) return -1;
1935         int rid = get_rid (ssid, lo_message_get_source (msg));
1936
1937         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1938
1939         if (s) {
1940                 if(s->pan_azimuth_control()) {
1941                         s->pan_azimuth_control()->set_value (pos, PBD::Controllable::NoGroup);
1942                 }
1943         }
1944
1945         return 0;
1946
1947 }
1948
1949 int
1950 OSC::route_set_pan_stereo_width (int ssid, float pos, lo_message msg)
1951 {
1952         if (!session) return -1;
1953         int rid = get_rid (ssid, lo_message_get_source (msg));
1954
1955         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1956
1957         if (s) {
1958                 if (s->pan_width_control()) {
1959                         s->pan_width_control()->set_value (pos, PBD::Controllable::NoGroup);
1960                 }
1961         }
1962
1963         return 0;
1964
1965 }
1966
1967 int
1968 OSC::route_set_send_gain_abs (int ssid, int sid, float val, lo_message msg)
1969 {
1970         if (!session) {
1971                 return -1;
1972         }
1973         int rid = get_rid (ssid, lo_message_get_source (msg));
1974
1975         boost::shared_ptr<Stripable> s = session->get_remote_nth_stripable (rid, PresentationInfo::Route);
1976
1977         if (!s) {
1978                 return -1;
1979         }
1980
1981         /* revert to zero-based counting */
1982
1983         if (sid > 0) {
1984                 --sid;
1985         }
1986
1987         if (s->send_level_controllable (sid)) {
1988                 s->send_level_controllable (sid)->set_value (val, PBD::Controllable::NoGroup);
1989         }
1990
1991         return 0;
1992 }
1993
1994 int
1995 OSC::route_set_send_gain_dB (int ssid, int sid, float val, lo_message msg)
1996 {
1997         return route_set_send_gain_abs (ssid, sid, dB_to_coefficient (val), msg);
1998 }
1999
2000 int
2001 OSC::route_set_send_fader (int ssid, int sid, float pos, lo_message msg)
2002 {
2003         if (!session) {
2004                 return -1;
2005         }
2006         int ret;
2007         if ((pos > 799.5) && (pos < 800.5)) {
2008                 ret = route_set_send_gain_abs (ssid, sid, 1.0, msg);
2009         } else {
2010                 ret = route_set_send_gain_abs (ssid, sid, slider_position_to_gain_with_max ((pos/1023), 2.0), msg);
2011         }
2012         return ret;
2013 }
2014
2015 int
2016 OSC::route_plugin_parameter (int ssid, int piid, int par, float val, lo_message msg)
2017 {
2018         if (!session)
2019                 return -1;
2020         int rid = get_rid (ssid, lo_message_get_source (msg));
2021
2022         boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
2023
2024         if (!r) {
2025                 PBD::error << "OSC: Invalid Remote Control ID '" << rid << "'" << endmsg;
2026                 return -1;
2027         }
2028
2029         boost::shared_ptr<Processor> redi=r->nth_plugin (piid);
2030
2031         if (!redi) {
2032                 PBD::error << "OSC: cannot find plugin # " << piid << " for RID '" << rid << "'" << endmsg;
2033                 return -1;
2034         }
2035
2036         boost::shared_ptr<PluginInsert> pi;
2037
2038         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
2039                 PBD::error << "OSC: given processor # " << piid << " on RID '" << rid << "' is not a Plugin." << endmsg;
2040                 return -1;
2041         }
2042
2043         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
2044         bool ok=false;
2045
2046         uint32_t controlid = pip->nth_parameter (par,ok);
2047
2048         if (!ok) {
2049                 PBD::error << "OSC: Cannot find parameter # " << par <<  " for plugin # " << piid << " on RID '" << rid << "'" << endmsg;
2050                 return -1;
2051         }
2052
2053         if (!pip->parameter_is_input(controlid)) {
2054                 PBD::error << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << rid << "' is not a control input" << endmsg;
2055                 return -1;
2056         }
2057
2058         ParameterDescriptor pd;
2059         pi->plugin()->get_parameter_descriptor (controlid,pd);
2060
2061         if (val >= pd.lower && val <= pd.upper) {
2062
2063                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
2064                 // cerr << "parameter:" << redi->describe_parameter(controlid) << " val:" << val << "\n";
2065                 c->set_value (val, PBD::Controllable::NoGroup);
2066         } else {
2067                 PBD::warning << "OSC: Parameter # " << par <<  " for plugin # " << piid << " on RID '" << rid << "' is out of range" << endmsg;
2068                 PBD::info << "OSC: Valid range min=" << pd.lower << " max=" << pd.upper << endmsg;
2069         }
2070
2071         return 0;
2072 }
2073
2074 //prints to cerr only
2075 int
2076 OSC::route_plugin_parameter_print (int ssid, int piid, int par, lo_message msg)
2077 {
2078         if (!session) {
2079                 return -1;
2080         }
2081         int rid = get_rid (ssid, lo_message_get_source (msg));
2082
2083         boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
2084
2085         if (!r) {
2086                 return -1;
2087         }
2088
2089         boost::shared_ptr<Processor> redi=r->nth_processor (piid);
2090
2091         if (!redi) {
2092                 return -1;
2093         }
2094
2095         boost::shared_ptr<PluginInsert> pi;
2096
2097         if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
2098                 return -1;
2099         }
2100
2101         boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
2102         bool ok=false;
2103
2104         uint32_t controlid = pip->nth_parameter (par,ok);
2105
2106         if (!ok) {
2107                 return -1;
2108         }
2109
2110         ParameterDescriptor pd;
2111
2112         if (pi->plugin()->get_parameter_descriptor (controlid, pd) == 0) {
2113                 boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
2114
2115                 cerr << "parameter:     " << redi->describe_parameter(controlid)  << "\n";
2116                 cerr << "current value: " << c->get_value ();
2117                 cerr << "lower value:   " << pd.lower << "\n";
2118                 cerr << "upper value:   " << pd.upper << "\n";
2119         }
2120
2121         return 0;
2122 }
2123
2124 void
2125 OSC::gui_selection_changed (StripableNotificationListPtr stripables)
2126 {
2127         boost::shared_ptr<Stripable> strip;
2128
2129         if (!stripables->empty()) {
2130                 strip = stripables->front().lock();
2131         }
2132         if (strip) {
2133                 for (uint32_t it = 0; it < _surface.size(); ++it) {
2134                         OSCSurface* sur = &_surface[it];
2135                         if(!sur->feedback[10]) {
2136                                 uint32_t sel_strip = strip->presentation_info().order() + 1;
2137                                 if (!(sel_strip < sur->bank) && !(sel_strip >= (sur->bank + sur->bank_size))) {
2138                                         lo_address addr = lo_address_new_from_url (sur->remote_url.c_str());
2139                                         _strip_select ((sel_strip - sur->bank + 1), addr);
2140                                 }
2141                         }
2142                 }
2143         }
2144
2145 }
2146
2147 // timer callbacks
2148 bool
2149 OSC::periodic (void)
2150 {
2151         for (GlobalObservers::iterator x = global_observers.begin(); x != global_observers.end(); x++) {
2152
2153                 OSCGlobalObserver* go;
2154
2155                 if ((go = dynamic_cast<OSCGlobalObserver*>(*x)) != 0) {
2156                         go->tick();
2157                 }
2158         }
2159         for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); x++) {
2160
2161                 OSCRouteObserver* ro;
2162
2163                 if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
2164                         ro->tick();
2165                 }
2166         }
2167         for (uint32_t it = 0; it < _surface.size(); ++it) {
2168                 OSCSurface* sur = &_surface[it];
2169                 OSCSelectObserver* so;
2170                 if ((so = dynamic_cast<OSCSelectObserver*>(sur->sel_obs)) != 0) {
2171                         so->tick();
2172                 }
2173         }
2174         return true;
2175 }
2176
2177 int
2178 OSC::route_send_fail (string path, uint32_t ssid, float val, lo_address addr)
2179 {
2180         OSCSurface *sur = get_surface(addr);
2181
2182         ostringstream os;
2183         lo_message reply;
2184         if (ssid) {
2185                 reply = lo_message_new ();
2186                 if (sur->feedback[2]) {
2187                         os << "/strip/" << path << "/" << ssid;
2188                 } else {
2189                         os << "/strip/" << path;
2190                         lo_message_add_int32 (reply, ssid);
2191                 }
2192                 string str_pth = os.str();
2193                 lo_message_add_float (reply, (float) val);
2194
2195                 lo_send_message (addr, str_pth.c_str(), reply);
2196                 lo_message_free (reply);
2197         }
2198         if (sur->surface_sel == ssid) {
2199                 os.str("");
2200                 os << "/select/" << path;
2201                 string sel_pth = os.str();
2202                 reply = lo_message_new ();
2203                 lo_message_add_float (reply, (float) val);
2204                 lo_send_message (addr, sel_pth.c_str(), reply);
2205                 lo_message_free (reply);
2206         }
2207
2208         return 0;
2209 }
2210
2211 XMLNode&
2212 OSC::get_state ()
2213 {
2214         XMLNode& node (ControlProtocol::get_state());
2215         node.add_property("debugmode", (int) _debugmode); // TODO: enum2str
2216         return node;
2217 }
2218
2219 int
2220 OSC::set_state (const XMLNode& node, int version)
2221 {
2222         if (ControlProtocol::set_state (node, version)) {
2223                 return -1;
2224         }
2225         XMLProperty const * p = node.property (X_("debugmode"));
2226         if (p) {
2227                 _debugmode = OSCDebugMode (PBD::atoi(p->value ()));
2228         }
2229
2230         return 0;
2231 }