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