~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to libs/surfaces/osc/osc.cc

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <iostream>
 
21
#include <fstream>
 
22
#include <cstdio>
 
23
#include <cstdlib>
 
24
#include <cerrno>
 
25
#include <algorithm>
 
26
 
 
27
#include <sys/poll.h>
 
28
#include <unistd.h>
 
29
#include <fcntl.h>
 
30
 
 
31
#include <glibmm/miscutils.h>
 
32
 
 
33
#include <pbd/pthread_utils.h>
 
34
#include <pbd/file_utils.h>
 
35
#include <pbd/failed_constructor.h>
 
36
 
 
37
#include "ardour/amp.h"
 
38
#include "ardour/session.h"
 
39
#include "ardour/route.h"
 
40
#include "ardour/audio_track.h"
 
41
#include "ardour/midi_track.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/send.h"
 
47
 
 
48
#include "osc.h"
 
49
#include "osc_controllable.h"
 
50
#include "osc_route_observer.h"
 
51
#include "i18n.h"
 
52
 
 
53
using namespace ARDOUR;
 
54
using namespace std;
 
55
using namespace Glib;
 
56
 
 
57
#include "pbd/abstract_ui.cc" // instantiate template
 
58
 
 
59
OSC* OSC::_instance = 0;
 
60
 
 
61
#ifdef DEBUG
 
62
static void error_callback(int num, const char *m, const char *path)
 
63
{
 
64
        fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
 
65
}
 
66
#else
 
67
static void error_callback(int, const char *, const char *)
 
68
{
 
69
 
 
70
}
 
71
#endif
 
72
 
 
73
OSC::OSC (Session& s, uint32_t port)
 
74
        : ControlProtocol (s, "OSC")
 
75
        , AbstractUI<OSCUIRequest> ("osc")
 
76
        , _port(port)
 
77
{
 
78
        _instance = this;
 
79
        _shutdown = false;
 
80
        _osc_server = 0;
 
81
        _osc_unix_server = 0;
 
82
        _namespace_root = "/ardour";
 
83
        _send_route_changes = true;
 
84
 
 
85
        /* glibmm hack */
 
86
        local_server = 0;
 
87
        remote_server = 0;
 
88
 
 
89
        // "Application Hooks"
 
90
        session_loaded (s);
 
91
        session->Exported.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::session_exported, this, _1, _2), this);
 
92
}
 
93
 
 
94
OSC::~OSC()
 
95
{
 
96
        stop ();
 
97
        _instance = 0;
 
98
}
 
99
 
 
100
void
 
101
OSC::do_request (OSCUIRequest* req)
 
102
{
 
103
        if (req->type == CallSlot) {
 
104
 
 
105
                call_slot (MISSING_INVALIDATOR, req->the_slot);
 
106
 
 
107
        } else if (req->type == Quit) {
 
108
 
 
109
                stop ();
 
110
        }
 
111
}
 
112
 
 
113
int
 
114
OSC::set_active (bool yn)
 
115
{
 
116
        if (yn) {
 
117
                return start ();
 
118
        } else {
 
119
                return stop ();
 
120
        }
 
121
}
 
122
 
 
123
bool
 
124
OSC::get_active () const
 
125
{
 
126
        return _osc_server != 0;
 
127
}
 
128
 
 
129
int 
 
130
OSC::set_feedback (bool yn)
 
131
{
 
132
        _send_route_changes = yn;
 
133
        return 0;
 
134
}
 
135
 
 
136
bool
 
137
OSC::get_feedback () const
 
138
{
 
139
        return _send_route_changes;
 
140
}
 
141
 
 
142
int
 
143
OSC::start ()
 
144
{
 
145
        char tmpstr[255];
 
146
 
 
147
        if (_osc_server) {
 
148
                /* already started */
 
149
                return 0;
 
150
        }
 
151
        
 
152
        for (int j=0; j < 20; ++j) {
 
153
                snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
 
154
                
 
155
                //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
 
156
                //      break;
 
157
                //}
 
158
                
 
159
                if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
 
160
                        break;
 
161
                }
 
162
 
 
163
#ifdef DEBUG            
 
164
                cerr << "can't get osc at port: " << _port << endl;
 
165
#endif
 
166
                _port++;
 
167
                continue;
 
168
        }
 
169
 
 
170
        if (!_osc_server) {
 
171
                return 1;
 
172
        }
 
173
        
 
174
#ifdef ARDOUR_OSC_UNIX_SERVER
 
175
        
 
176
        // APPEARS sluggish for now
 
177
        
 
178
        // attempt to create unix socket server too
 
179
        
 
180
        snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
 
181
        int fd = mkstemp(tmpstr);
 
182
        
 
183
        if (fd >= 0 ) {
 
184
                unlink (tmpstr);
 
185
                close (fd);
 
186
                
 
187
                _osc_unix_server = lo_server_new (tmpstr, error_callback);
 
188
                
 
189
                if (_osc_unix_server) {
 
190
                        _osc_unix_socket_path = tmpstr;
 
191
                }
 
192
        }
 
193
#endif
 
194
        
 
195
        PBD::info << "OSC @ " << get_server_url () << endmsg;
 
196
 
 
197
        std::string url_file;
 
198
 
 
199
        if (find_file_in_search_path (ardour_config_search_path(), "osc_url", url_file)) {
 
200
                
 
201
                _osc_url_file = url_file;
 
202
                ofstream urlfile;
 
203
                urlfile.open(_osc_url_file.c_str(), ios::trunc);
 
204
                
 
205
                if (urlfile) {
 
206
                        urlfile << get_server_url () << endl;
 
207
                        urlfile.close();
 
208
                } else {  
 
209
                        cerr << "Couldn't write '" <<  _osc_url_file << "'" <<endl;
 
210
                }
 
211
        }
 
212
        
 
213
        register_callbacks();
 
214
        
 
215
        // lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
 
216
 
 
217
        /* startup the event loop thread */
 
218
 
 
219
        BaseUI::run ();
 
220
 
 
221
        return 0;
 
222
}
 
223
 
 
224
void
 
225
OSC::thread_init ()
 
226
{
 
227
        pthread_set_name (X_("OSC"));
 
228
 
 
229
        if (_osc_unix_server) {
 
230
                Glib::RefPtr<IOSource> src = IOSource::create (lo_server_get_socket_fd (_osc_unix_server), IO_IN|IO_HUP|IO_ERR);
 
231
                src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_unix_server));
 
232
                src->attach (_main_loop->get_context());
 
233
                local_server = src->gobj();
 
234
                g_source_ref (local_server);
 
235
        }
 
236
 
 
237
        if (_osc_server) {
 
238
                Glib::RefPtr<IOSource> src  = IOSource::create (lo_server_get_socket_fd (_osc_server), IO_IN|IO_HUP|IO_ERR);
 
239
                src->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler), _osc_server));
 
240
                src->attach (_main_loop->get_context());
 
241
                remote_server = src->gobj();
 
242
                g_source_ref (remote_server);
 
243
        }
 
244
 
 
245
        PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("OSC"), 2048);
 
246
        SessionEvent::create_per_thread_pool (X_("OSC"), 128);
 
247
}
 
248
 
 
249
int
 
250
OSC::stop ()
 
251
{
 
252
        /* stop main loop */
 
253
 
 
254
        if (local_server) {
 
255
                g_source_destroy (local_server);
 
256
                g_source_unref (local_server);
 
257
                local_server = 0;
 
258
        }
 
259
 
 
260
        if (remote_server) {
 
261
                g_source_destroy (remote_server);
 
262
                g_source_unref (remote_server);
 
263
                remote_server = 0;
 
264
        }
 
265
 
 
266
        BaseUI::quit ();
 
267
 
 
268
        if (_osc_server) {
 
269
                int fd = lo_server_get_socket_fd(_osc_server);
 
270
                if (fd >=0) {
 
271
                        close(fd);
 
272
                }
 
273
                lo_server_free (_osc_server);
 
274
                _osc_server = 0;
 
275
        }
 
276
 
 
277
        if (_osc_unix_server) {
 
278
                int fd = lo_server_get_socket_fd(_osc_unix_server);
 
279
                if (fd >=0) {
 
280
                        close(fd);
 
281
                }
 
282
                lo_server_free (_osc_unix_server);
 
283
                _osc_unix_server = 0;
 
284
        }
 
285
        
 
286
        if (!_osc_unix_socket_path.empty()) {
 
287
                unlink (_osc_unix_socket_path.c_str());
 
288
        }
 
289
        
 
290
        if (!_osc_url_file.empty() ) {
 
291
                unlink (_osc_url_file.c_str() );
 
292
        }
 
293
 
 
294
        // Delete any active route observers
 
295
        for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
 
296
 
 
297
                OSCRouteObserver* rc;
 
298
                
 
299
                if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
 
300
                        delete *x;
 
301
                        x = route_observers.erase (x);
 
302
                } else {
 
303
                        ++x;
 
304
                }
 
305
        }
 
306
        
 
307
        return 0;
 
308
}
 
309
 
 
310
void
 
311
OSC::register_callbacks()
 
312
{
 
313
        lo_server srvs[2];
 
314
        lo_server serv;
 
315
 
 
316
        srvs[0] = _osc_server;
 
317
        srvs[1] = _osc_unix_server;
 
318
        
 
319
        for (size_t i = 0; i < 2; ++i) {
 
320
 
 
321
                if (!srvs[i]) {
 
322
                        continue;
 
323
                }
 
324
 
 
325
                serv = srvs[i];
 
326
                
 
327
                /* this is a special catchall handler */
 
328
                
 
329
                lo_server_add_method (serv, 0, 0, _catchall, this);
 
330
                
 
331
#define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this)
 
332
                
 
333
                REGISTER_CALLBACK (serv, "/routes/list", "", routes_list);
 
334
                REGISTER_CALLBACK (serv, "/ardour/add_marker", "", add_marker);
 
335
                REGISTER_CALLBACK (serv, "/ardour/access_action", "s", access_action);
 
336
                REGISTER_CALLBACK (serv, "/ardour/loop_toggle", "", loop_toggle);
 
337
                REGISTER_CALLBACK (serv, "/ardour/goto_start", "", goto_start);
 
338
                REGISTER_CALLBACK (serv, "/ardour/goto_end", "", goto_end);
 
339
                REGISTER_CALLBACK (serv, "/ardour/rewind", "", rewind);
 
340
                REGISTER_CALLBACK (serv, "/ardour/ffwd", "", ffwd);
 
341
                REGISTER_CALLBACK (serv, "/ardour/transport_stop", "", transport_stop);
 
342
                REGISTER_CALLBACK (serv, "/ardour/transport_play", "", transport_play);
 
343
                REGISTER_CALLBACK (serv, "/ardour/transport_frame", "", transport_frame);
 
344
                REGISTER_CALLBACK (serv, "/ardour/set_transport_speed", "f", set_transport_speed);
 
345
                REGISTER_CALLBACK (serv, "/ardour/locate", "ii", locate);
 
346
                REGISTER_CALLBACK (serv, "/ardour/save_state", "", save_state);
 
347
                REGISTER_CALLBACK (serv, "/ardour/prev_marker", "", prev_marker);
 
348
                REGISTER_CALLBACK (serv, "/ardour/next_marker", "", next_marker);
 
349
                REGISTER_CALLBACK (serv, "/ardour/undo", "", undo);
 
350
                REGISTER_CALLBACK (serv, "/ardour/redo", "", redo);
 
351
                REGISTER_CALLBACK (serv, "/ardour/toggle_punch_in", "", toggle_punch_in);
 
352
                REGISTER_CALLBACK (serv, "/ardour/toggle_punch_out", "", toggle_punch_out);
 
353
                REGISTER_CALLBACK (serv, "/ardour/rec_enable_toggle", "", rec_enable_toggle);
 
354
                REGISTER_CALLBACK (serv, "/ardour/toggle_all_rec_enables", "", toggle_all_rec_enables);
 
355
 
 
356
                REGISTER_CALLBACK (serv, "/ardour/routes/mute", "ii", route_mute);
 
357
                REGISTER_CALLBACK (serv, "/ardour/routes/solo", "ii", route_solo);
 
358
                REGISTER_CALLBACK (serv, "/ardour/routes/recenable", "ii", route_recenable);
 
359
                REGISTER_CALLBACK (serv, "/ardour/routes/gainabs", "if", route_set_gain_abs);
 
360
                REGISTER_CALLBACK (serv, "/ardour/routes/gaindB", "if", route_set_gain_dB);
 
361
                REGISTER_CALLBACK (serv, "/ardour/routes/pan_stereo_position", "if", route_set_pan_stereo_position);
 
362
                REGISTER_CALLBACK (serv, "/ardour/routes/pan_stereo_width", "if", route_set_pan_stereo_width);
 
363
                REGISTER_CALLBACK (serv, "/ardour/routes/plugin/parameter", "iiif", route_plugin_parameter);
 
364
                REGISTER_CALLBACK (serv, "/ardour/routes/plugin/parameter/print", "iii", route_plugin_parameter_print);
 
365
                REGISTER_CALLBACK (serv, "/ardour/routes/send/gainabs", "iif", route_set_send_gain_abs);
 
366
                REGISTER_CALLBACK (serv, "/ardour/routes/send/gaindB", "iif", route_set_send_gain_dB);
 
367
 
 
368
                /* still not-really-standardized query interface */
 
369
                //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
 
370
                //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
 
371
 
 
372
                // un/register_update args= s:ctrl s:returl s:retpath
 
373
                //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
 
374
                //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
 
375
                //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
 
376
                //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
 
377
 
 
378
        }
 
379
}
 
380
 
 
381
bool
 
382
OSC::osc_input_handler (IOCondition ioc, lo_server srv)
 
383
{
 
384
        if (ioc & ~IO_IN) {
 
385
                return false;
 
386
        }
 
387
 
 
388
        if (ioc & IO_IN) {
 
389
                lo_server_recv (srv);
 
390
        }
 
391
 
 
392
        return true;
 
393
}
 
394
 
 
395
std::string
 
396
OSC::get_server_url()
 
397
{
 
398
        string url;
 
399
        char * urlstr;
 
400
 
 
401
        if (_osc_server) {
 
402
                urlstr = lo_server_get_url (_osc_server);
 
403
                url = urlstr;
 
404
                free (urlstr);
 
405
        }
 
406
        
 
407
        return url;
 
408
}
 
409
 
 
410
std::string
 
411
OSC::get_unix_server_url()
 
412
{
 
413
        string url;
 
414
        char * urlstr;
 
415
 
 
416
        if (_osc_unix_server) {
 
417
                urlstr = lo_server_get_url (_osc_unix_server);
 
418
                url = urlstr;
 
419
                free (urlstr);
 
420
        }
 
421
        
 
422
        return url;
 
423
}
 
424
 
 
425
void
 
426
OSC::listen_to_route (boost::shared_ptr<Route> route, lo_address addr)
 
427
{
 
428
        /* avoid duplicate listens */
 
429
        
 
430
        for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); ++x) {
 
431
                
 
432
                OSCRouteObserver* ro;
 
433
 
 
434
                if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
 
435
 
 
436
                        int res = strcmp(lo_address_get_hostname(ro->address()), lo_address_get_hostname(addr));
 
437
                        
 
438
                        if (ro->route() == route && res == 0) {
 
439
                                return;
 
440
                        }
 
441
                }
 
442
        }
 
443
 
 
444
        OSCRouteObserver* o = new OSCRouteObserver (route, addr);
 
445
        route_observers.push_back (o);
 
446
 
 
447
        route->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr<Route> (route)), this);
 
448
}
 
449
 
 
450
void
 
451
OSC::drop_route (boost::weak_ptr<Route> wr)
 
452
{
 
453
        boost::shared_ptr<Route> r = wr.lock ();
 
454
 
 
455
        if (!r) {
 
456
                return;
 
457
        }
 
458
 
 
459
        for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) {
 
460
 
 
461
                OSCRouteObserver* rc;
 
462
                
 
463
                if ((rc = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
 
464
                  
 
465
                        if (rc->route() == r) {
 
466
                                delete *x;
 
467
                                x = route_observers.erase (x);
 
468
                        } else {
 
469
                                ++x;
 
470
                        }
 
471
                } else {
 
472
                        ++x;
 
473
                }
 
474
        }
 
475
}
 
476
 
 
477
void
 
478
OSC::end_listen (boost::shared_ptr<Route> r, lo_address addr)
 
479
{
 
480
        RouteObservers::iterator x;
 
481
        
 
482
        // Remove the route observers
 
483
        for (x = route_observers.begin(); x != route_observers.end();) {
 
484
 
 
485
                OSCRouteObserver* ro;
 
486
                
 
487
                if ((ro = dynamic_cast<OSCRouteObserver*>(*x)) != 0) {
 
488
                  
 
489
                        int res = strcmp(lo_address_get_hostname(ro->address()), lo_address_get_hostname(addr));
 
490
 
 
491
                        if (ro->route() == r && res == 0) {
 
492
                                delete *x;
 
493
                                x = route_observers.erase (x);
 
494
                        }
 
495
                        else {
 
496
                                ++x;
 
497
                        }
 
498
                }
 
499
                else {
 
500
                        ++x;
 
501
                }
 
502
        }
 
503
}
 
504
 
 
505
void
 
506
OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg)
 
507
{
 
508
        char* subpath;
 
509
        
 
510
        subpath = (char*) malloc (len-15+1);
 
511
        memcpy (subpath, path, len-15);
 
512
        subpath[len-15] = '\0';
 
513
        
 
514
        send_current_value (subpath, argv, argc, msg);
 
515
        
 
516
        free (subpath);
 
517
}
 
518
 
 
519
void
 
520
OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg)
 
521
{
 
522
        if (!session) {
 
523
                return;
 
524
        }
 
525
 
 
526
        lo_message reply = lo_message_new ();
 
527
        boost::shared_ptr<Route> r;
 
528
        int id;
 
529
 
 
530
        lo_message_add_string (reply, path);
 
531
        
 
532
        if (argc == 0) {
 
533
                lo_message_add_string (reply, "bad syntax");
 
534
        } else {
 
535
                id = argv[0]->i;
 
536
                r = session->route_by_remote_id (id);
 
537
 
 
538
                if (!r) {
 
539
                        lo_message_add_string (reply, "not found");
 
540
                } else {
 
541
 
 
542
                        if (strcmp (path, "/routes/state") == 0) {
 
543
                                
 
544
                                if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
 
545
                                        lo_message_add_string (reply, "AT");
 
546
                                } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
 
547
                                        lo_message_add_string (reply, "MT");
 
548
                                } else {
 
549
                                        lo_message_add_string (reply, "B");
 
550
                                }
 
551
                                
 
552
                                lo_message_add_string (reply, r->name().c_str());
 
553
                                lo_message_add_int32 (reply, r->n_inputs().n_audio());
 
554
                                lo_message_add_int32 (reply, r->n_outputs().n_audio());
 
555
                                lo_message_add_int32 (reply, r->muted());
 
556
                                lo_message_add_int32 (reply, r->soloed());
 
557
                                
 
558
                        } else if (strcmp (path, "/routes/mute") == 0) {
 
559
                                
 
560
                                lo_message_add_int32 (reply, (float) r->muted());
 
561
                                
 
562
                        } else if (strcmp (path, "/routes/solo") == 0) {
 
563
                                
 
564
                                lo_message_add_int32 (reply, r->soloed());
 
565
                        }
 
566
                }
 
567
        }
 
568
 
 
569
        lo_send_message (lo_message_get_source (msg), "#reply", reply);
 
570
        lo_message_free (reply);
 
571
}
 
572
        
 
573
int
 
574
OSC::_catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) 
 
575
{
 
576
        return ((OSC*)user_data)->catchall (path, types, argv, argc, data);
 
577
}
 
578
 
 
579
int
 
580
OSC::catchall (const char *path, const char* /*types*/, lo_arg **argv, int argc, lo_message msg) 
 
581
{
 
582
        size_t len;
 
583
        int ret = 1; /* unhandled */
 
584
 
 
585
        //cerr << "Received a message, path = " << path << " types = \"" 
 
586
        //     << (types ? types : "NULL") << '"' << endl;
 
587
 
 
588
        /* 15 for /#current_value plus 2 for /<path> */
 
589
 
 
590
        len = strlen (path);
 
591
 
 
592
        if (len >= 17 && !strcmp (&path[len-15], "/#current_value")) {
 
593
                current_value_query (path, len, argv, argc, msg);
 
594
                ret = 0;
 
595
 
 
596
        } else if (strcmp (path, "/routes/listen") == 0) {
 
597
                
 
598
                cerr << "set up listener\n";
 
599
 
 
600
                lo_message reply = lo_message_new ();
 
601
 
 
602
                if (argc <= 0) {
 
603
                        lo_message_add_string (reply, "syntax error");
 
604
                } else {
 
605
                        for (int n = 0; n < argc; ++n) {
 
606
 
 
607
                                boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
 
608
                                
 
609
                                if (!r) {
 
610
                                        lo_message_add_string (reply, "not found");
 
611
                                        cerr << "no such route\n";
 
612
                                        break;
 
613
                                } else {                        
 
614
                                        cerr << "add listener\n";
 
615
                                        listen_to_route (r, lo_message_get_source (msg));
 
616
                                        lo_message_add_int32 (reply, argv[n]->i);
 
617
                                }
 
618
                        }
 
619
                }
 
620
 
 
621
                lo_send_message (lo_message_get_source (msg), "#reply", reply);
 
622
                lo_message_free (reply);
 
623
                
 
624
                ret = 0;
 
625
 
 
626
        } else if (strcmp (path, "/routes/ignore") == 0) {
 
627
 
 
628
                for (int n = 0; n < argc; ++n) {
 
629
 
 
630
                        boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
 
631
                        
 
632
                        if (r) {
 
633
                                end_listen (r, lo_message_get_source (msg));
 
634
                        }
 
635
                }
 
636
                
 
637
                ret = 0;        
 
638
        } 
 
639
 
 
640
        return ret;
 
641
}
 
642
 
 
643
void
 
644
OSC::update_clock ()
 
645
{
 
646
  
 
647
}
 
648
 
 
649
// "Application Hook" Handlers //
 
650
void
 
651
OSC::session_loaded (Session& s)
 
652
{
 
653
        lo_address listener = lo_address_new (NULL, "7770");
 
654
        lo_send (listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str());
 
655
}
 
656
 
 
657
void
 
658
OSC::session_exported (std::string path, std::string name)
 
659
{
 
660
        lo_address listener = lo_address_new (NULL, "7770");
 
661
        lo_send (listener, "/session/exported", "ss", path.c_str(), name.c_str());
 
662
}
 
663
 
 
664
// end "Application Hook" Handlers //
 
665
 
 
666
/* path callbacks */
 
667
 
 
668
int 
 
669
OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv*/, int /*argc*/, void */*data*/, void* /*user_data*/) 
 
670
 
671
#if 0
 
672
        const char* returl;
 
673
 
 
674
        if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != s) {
 
675
                return 1;
 
676
        }
 
677
 
 
678
        const char *returl = argv[1]->s;
 
679
        lo_address addr = find_or_cache_addr (returl);
 
680
 
 
681
        const char *retpath = argv[2]->s;
 
682
 
 
683
        
 
684
        if (strcmp (argv[0]->s, "transport_frame") == 0) {
 
685
 
 
686
                if (session) {
 
687
                        lo_send (addr, retpath, "i", session->transport_frame());
 
688
                }
 
689
 
 
690
        } else if (strcmp (argv[0]->s, "transport_speed") == 0) {
 
691
                
 
692
                if (session) {
 
693
                        lo_send (addr, retpath, "i", session->transport_frame());
 
694
                }
 
695
                
 
696
        } else if (strcmp (argv[0]->s, "transport_locked") == 0) {
 
697
                
 
698
                if (session) {
 
699
                        lo_send (addr, retpath, "i", session->transport_frame());
 
700
                }
 
701
                
 
702
        } else if (strcmp (argv[0]->s, "punch_in") == 0) {
 
703
                
 
704
                if (session) {
 
705
                        lo_send (addr, retpath, "i", session->transport_frame());
 
706
                }
 
707
                
 
708
        } else if (strcmp (argv[0]->s, "punch_out") == 0) {
 
709
 
 
710
                if (session) {
 
711
                        lo_send (addr, retpath, "i", session->transport_frame());
 
712
                }
 
713
                
 
714
        } else if (strcmp (argv[0]->s, "rec_enable") == 0) {
 
715
                        
 
716
                if (session) {
 
717
                        lo_send (addr, retpath, "i", session->transport_frame());
 
718
                }
 
719
 
 
720
        } else {
 
721
 
 
722
                /* error */
 
723
        }
 
724
#endif
 
725
        return 0;
 
726
}
 
727
 
 
728
void
 
729
OSC::routes_list (lo_message msg)
 
730
{
 
731
        for (int n = 0; n < (int) session->nroutes(); ++n) {
 
732
 
 
733
                boost::shared_ptr<Route> r = session->route_by_remote_id (n);
 
734
                
 
735
                if (r) {
 
736
 
 
737
                        lo_message reply = lo_message_new ();
 
738
                
 
739
                        if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
 
740
                                lo_message_add_string (reply, "AT");
 
741
                        } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
 
742
                                lo_message_add_string (reply, "MT");
 
743
                        } else {
 
744
                                lo_message_add_string (reply, "B");
 
745
                        }
 
746
                        
 
747
                        lo_message_add_string (reply, r->name().c_str());
 
748
                        lo_message_add_int32 (reply, r->n_inputs().n_audio());
 
749
                        lo_message_add_int32 (reply, r->n_outputs().n_audio());
 
750
                        lo_message_add_int32 (reply, r->muted());
 
751
                        lo_message_add_int32 (reply, r->soloed());
 
752
                        lo_message_add_int32 (reply, r->remote_control_id());
 
753
                        
 
754
                        if (boost::dynamic_pointer_cast<AudioTrack>(r) 
 
755
                                || boost::dynamic_pointer_cast<MidiTrack>(r)) {
 
756
        
 
757
                                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
 
758
                                lo_message_add_int32 (reply, t->record_enabled());
 
759
                        }
 
760
 
 
761
                        //Automatically listen to routes listed
 
762
                        listen_to_route(r, lo_message_get_source (msg));
 
763
 
 
764
                        lo_send_message (lo_message_get_source (msg), "#reply", reply);
 
765
                        lo_message_free (reply);
 
766
                }
 
767
        }
 
768
        
 
769
        // Send end of listing message
 
770
        lo_message reply = lo_message_new ();
 
771
 
 
772
        lo_message_add_string (reply, "end_route_list");
 
773
        lo_message_add_int64 (reply, session->frame_rate());
 
774
        lo_message_add_int64 (reply, session->current_end_frame());
 
775
        
 
776
        lo_send_message (lo_message_get_source (msg), "#reply", reply);
 
777
        
 
778
        lo_message_free (reply);
 
779
}
 
780
 
 
781
void
 
782
OSC::transport_frame (lo_message msg)
 
783
{
 
784
                framepos_t pos = session->transport_frame ();
 
785
                
 
786
                lo_message reply = lo_message_new ();
 
787
                lo_message_add_int64 (reply, pos);
 
788
                
 
789
                lo_send_message (lo_message_get_source (msg), "/ardour/transport_frame", reply);
 
790
                
 
791
                lo_message_free (reply);
 
792
}
 
793
 
 
794
int
 
795
OSC::route_mute (int rid, int yn)
 
796
{
 
797
        if (!session) return -1;
 
798
 
 
799
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
800
 
 
801
        if (r) {
 
802
                r->set_mute (yn, this);
 
803
        }
 
804
        
 
805
        return 0;
 
806
}
 
807
 
 
808
int
 
809
OSC::route_solo (int rid, int yn)
 
810
{
 
811
        if (!session) return -1;
 
812
 
 
813
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
814
 
 
815
        if (r) {
 
816
                r->set_solo (yn, this);
 
817
        }
 
818
        
 
819
        return 0;
 
820
}
 
821
 
 
822
int
 
823
OSC::route_recenable (int rid, int yn)
 
824
{
 
825
        if (!session) return -1;
 
826
 
 
827
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
828
 
 
829
        if (r) {
 
830
                r->set_record_enabled (yn, this);
 
831
        }
 
832
        
 
833
        return 0;
 
834
}
 
835
 
 
836
int
 
837
OSC::route_set_gain_abs (int rid, float level)
 
838
{
 
839
        if (!session) return -1;
 
840
 
 
841
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
842
 
 
843
        if (r) {
 
844
                r->set_gain (level, this);
 
845
        }
 
846
 
 
847
        return 0;
 
848
}
 
849
 
 
850
int
 
851
OSC::route_set_gain_dB (int rid, float dB)
 
852
{
 
853
        if (!session) return -1;
 
854
 
 
855
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
856
 
 
857
        if (r) {
 
858
                r->set_gain (dB_to_coefficient (dB), this);
 
859
        }
 
860
        
 
861
        return 0;
 
862
}
 
863
 
 
864
int
 
865
OSC::route_set_pan_stereo_position (int rid, float pos)
 
866
{
 
867
        if (!session) return -1;
 
868
 
 
869
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
870
 
 
871
        if (r) {
 
872
                boost::shared_ptr<Panner> panner = r->panner();
 
873
                if (panner) {
 
874
                        panner->set_position (pos);
 
875
                }
 
876
        }
 
877
        
 
878
        return 0;
 
879
 
 
880
}
 
881
 
 
882
int
 
883
OSC::route_set_pan_stereo_width (int rid, float pos)
 
884
{
 
885
        if (!session) return -1;
 
886
 
 
887
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
 
888
 
 
889
        if (r) {
 
890
                boost::shared_ptr<Panner> panner = r->panner();
 
891
                if (panner) {
 
892
                        panner->set_width (pos);
 
893
                }
 
894
        }
 
895
        
 
896
        return 0;
 
897
 
 
898
}
 
899
 
 
900
int
 
901
OSC::route_set_send_gain_abs (int rid, int sid, float val)
 
902
{
 
903
        if (!session) { 
 
904
                return -1;
 
905
        }
 
906
 
 
907
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);  
 
908
 
 
909
        if (!r) {
 
910
                return -1;
 
911
        }
 
912
 
 
913
        /* revert to zero-based counting */
 
914
 
 
915
        if (sid > 0) {
 
916
                --sid;
 
917
        }
 
918
 
 
919
        boost::shared_ptr<Processor> p = r->nth_send (sid);
 
920
        
 
921
        if (p) {
 
922
                boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
 
923
                boost::shared_ptr<Amp> a = s->amp();
 
924
                
 
925
                if (a) {
 
926
                        a->set_gain (val, this);
 
927
                }
 
928
        }
 
929
        return 0;
 
930
}
 
931
 
 
932
int
 
933
OSC::route_set_send_gain_dB (int rid, int sid, float val)
 
934
{
 
935
        if (!session) { 
 
936
                return -1;
 
937
        }
 
938
 
 
939
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);  
 
940
 
 
941
        if (!r) {
 
942
                return -1;
 
943
        }
 
944
 
 
945
        /* revert to zero-based counting */
 
946
 
 
947
        if (sid > 0) {
 
948
                --sid;
 
949
        }
 
950
 
 
951
        boost::shared_ptr<Processor> p = r->nth_send (sid);
 
952
        
 
953
        if (p) {
 
954
                boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
 
955
                boost::shared_ptr<Amp> a = s->amp();
 
956
                
 
957
                if (a) {
 
958
                        a->set_gain (dB_to_coefficient (val), this);
 
959
                }
 
960
        }
 
961
        return 0;
 
962
}
 
963
 
 
964
int
 
965
OSC::route_plugin_parameter (int rid, int piid, int par, float val)
 
966
{
 
967
        if (!session) { 
 
968
                return -1;
 
969
        }
 
970
 
 
971
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);  
 
972
 
 
973
        if (!r) {
 
974
                return -1;
 
975
        }
 
976
 
 
977
        boost::shared_ptr<Processor> redi=r->nth_processor (piid);
 
978
        
 
979
        if (!redi) {
 
980
                return -1;
 
981
        }
 
982
 
 
983
        boost::shared_ptr<PluginInsert> pi;
 
984
        
 
985
        if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
 
986
                return -1;
 
987
        }
 
988
 
 
989
        boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
 
990
        bool ok=false;
 
991
        
 
992
        uint32_t controlid = pip->nth_parameter (par,ok);
 
993
        
 
994
        if (!ok) {
 
995
                return -1;
 
996
        }
 
997
 
 
998
        Plugin::ParameterDescriptor pd;
 
999
        pi->plugin()->get_parameter_descriptor (controlid,pd);
 
1000
 
 
1001
        if (val >= pd.lower && val < pd.upper) {
 
1002
                
 
1003
                boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));;
 
1004
                cerr << "parameter:" << redi->describe_parameter(controlid) << " val:" << val << "\n";
 
1005
                c->set_value (val);
 
1006
        }  
 
1007
 
 
1008
        return 0;
 
1009
}
 
1010
 
 
1011
int
 
1012
OSC::route_plugin_parameter_print (int rid, int piid, int par)
 
1013
{
 
1014
        if (!session) { 
 
1015
                return -1;
 
1016
        }
 
1017
 
 
1018
        boost::shared_ptr<Route> r = session->route_by_remote_id (rid);  
 
1019
 
 
1020
        if (!r) {
 
1021
                return -1;
 
1022
        }
 
1023
 
 
1024
        boost::shared_ptr<Processor> redi=r->nth_processor (piid);
 
1025
        
 
1026
        if (!redi) {
 
1027
                return -1;
 
1028
        }
 
1029
 
 
1030
        boost::shared_ptr<PluginInsert> pi;
 
1031
        
 
1032
        if (!(pi = boost::dynamic_pointer_cast<PluginInsert>(redi))) {
 
1033
                return -1;
 
1034
        }
 
1035
        
 
1036
        boost::shared_ptr<ARDOUR::Plugin> pip = pi->plugin();
 
1037
        bool ok=false;
 
1038
        
 
1039
        uint32_t controlid = pip->nth_parameter (par,ok);
 
1040
        
 
1041
        if (!ok) {
 
1042
                return -1;
 
1043
        }
 
1044
 
 
1045
        Plugin::ParameterDescriptor pd;
 
1046
 
 
1047
        if (pi->plugin()->get_parameter_descriptor (controlid, pd) == 0) {
 
1048
                boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter(PluginAutomation, 0, controlid));
 
1049
                
 
1050
                cerr << "parameter:     " << redi->describe_parameter(controlid)  << "\n";
 
1051
                cerr << "current value: " << c->get_value ();
 
1052
                cerr << "lower value:   " << pd.lower << "\n";
 
1053
                cerr << "upper value:   " << pd.upper << "\n";
 
1054
        }
 
1055
 
 
1056
        return 0;
 
1057
}
 
1058
 
 
1059
XMLNode& 
 
1060
OSC::get_state () 
 
1061
{
 
1062
        XMLNode* node = new XMLNode ("Protocol"); 
 
1063
 
 
1064
        node->add_property (X_("name"), "Open Sound Control (OSC)");
 
1065
        node->add_property (X_("feedback"), _send_route_changes ? "1" : "0");
 
1066
 
 
1067
        return *node;
 
1068
}
 
1069
 
 
1070
int 
 
1071
OSC::set_state (const XMLNode&, int /*version*/)
 
1072
{
 
1073
        return 0;
 
1074
}