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