View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0003587 | ardour | features | public | 2010-12-05 21:23 | 2020-04-19 20:14 |
| Reporter | lincoln | Assigned To | lincoln | ||
| Priority | normal | Severity | feature | Reproducibility | N/A |
| Status | closed | Resolution | fixed | ||
| Target Version | 3.0-beta1 | ||||
| Summary | 0003587: OSC modifications for Ardroid | ||||
| Description | Ardroid requires some modifications to the OSC code to support its features. Attached are patches that add capability to query for track list, and initial work to create the notion of an OSC Observable, where an OSC client can observe changes in properties on the Ardour side and make them visible on the remote. This work most likely needs a through clean up, but I am placing it here so that those wishing to thinker with Ardroid can see all the functionality. | ||||
| Tags | No tags attached. | ||||
|
2010-12-05 21:23
|
osc-adds-for-ardroid.patch (10,926 bytes)
Index: libs/surfaces/osc/osc.cc
===================================================================
--- libs/surfaces/osc/osc.cc (revision 8177)
+++ libs/surfaces/osc/osc.cc (working copy)
@@ -47,6 +47,7 @@
#include "osc.h"
#include "osc_controllable.h"
+#include "osc_route_observer.h"
#include "i18n.h"
using namespace ARDOUR;
@@ -153,9 +154,14 @@
for (int j=0; j < 20; ++j) {
snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
+ //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
+ // break;
+ //}
+
if ((_osc_server = lo_server_new (tmpstr, error_callback))) {
break;
}
+
#ifdef DEBUG
cerr << "can't get osc at port: " << _port << endl;
#endif
@@ -190,16 +196,16 @@
if (find_file_in_search_path (ardour_search_path() + system_config_search_path(),
"osc_url", url_file)) {
+
_osc_url_file = url_file.to_string();
ofstream urlfile;
urlfile.open(_osc_url_file.c_str(), ios::trunc);
- if ( urlfile )
- {
+
+ if ( urlfile ){
urlfile << get_server_url () << endl;
urlfile.close();
}
- else
- {
+ else {
cerr << "Couldn't write '" << _osc_url_file << "'" <<endl;
}
}
@@ -322,6 +328,7 @@
REGISTER_CALLBACK (serv, "/ardour/ffwd", "", ffwd);
REGISTER_CALLBACK (serv, "/ardour/transport_stop", "", transport_stop);
REGISTER_CALLBACK (serv, "/ardour/transport_play", "", transport_play);
+ //REGISTER_CALLBACK (serv, "/ardour/transport_frame", "", transport_frame);
REGISTER_CALLBACK (serv, "/ardour/set_transport_speed", "f", set_transport_speed);
REGISTER_CALLBACK (serv, "/ardour/locate", "ii", locate);
REGISTER_CALLBACK (serv, "/ardour/save_state", "", save_state);
@@ -345,19 +352,17 @@
REGISTER_CALLBACK (serv, "/ardour/routes/plugin/parameter/print", "iii", route_plugin_parameter_print);
-#if 0
+
/* still not-really-standardized query interface */
- REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
- REGISTER_CALLBACK (serv, "/ardour/set", "", set);
-#endif
+ //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
+ //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
-#if 0
// un/register_update args= s:ctrl s:returl s:retpath
- lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
- lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
- lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
- lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
-#endif
+ //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
+ //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
+ //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
+ //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
+
}
}
@@ -486,8 +491,8 @@
size_t len;
int ret = 1; /* unhandled */
- cerr << "Received a message, path = " << path << " types = \""
- << (types ? types : "NULL") << '"' << endl;
+ //cerr << "Received a message, path = " << path << " types = \""
+ // << (types ? types : "NULL") << '"' << endl;
/* 15 for /#current_value plus 2 for /<path> */
@@ -496,7 +501,19 @@
if (len >= 17 && !strcmp (&path[len-15], "/#current_value")) {
current_value_query (path, len, argv, argc, msg);
ret = 0;
-
+ } else if (strcmp (path, "/ardour/transport_frame") == 0) {
+
+ framepos_t pos = transport_frame ();
+
+ lo_message reply = lo_message_new ();
+ lo_message_add_int64 (reply, pos);
+
+ lo_send_message (lo_message_get_source (msg), "/ardour/transport_frame", reply);
+
+ lo_message_free (reply);
+
+ ret = 0;
+
} else if (strcmp (path, "/routes/listen") == 0) {
cerr << "set up listener\n";
@@ -524,6 +541,8 @@
lo_send_message (lo_message_get_source (msg), "#reply", reply);
lo_message_free (reply);
+
+ ret = 0;
} else if (strcmp (path, "/routes/ignore") == 0) {
@@ -535,12 +554,72 @@
end_listen (r, lo_message_get_source (msg));
}
}
+
+ ret = 0;
+
+ } else if (strcmp (path, "/routes/list") == 0) {
+
+ for (int n = 0; n < (int) session->nroutes(); ++n) {
+
+ boost::shared_ptr<Route> r = session->route_by_remote_id (n);
+
+ if (r) {
+
+ lo_message reply = lo_message_new ();
+
+ if (boost::dynamic_pointer_cast<AudioTrack>(r)) {
+ lo_message_add_string (reply, "AT");
+ } else if (boost::dynamic_pointer_cast<MidiTrack>(r)) {
+ lo_message_add_string (reply, "MT");
+ } else {
+ lo_message_add_string (reply, "B");
+ }
+
+ lo_message_add_string (reply, r->name().c_str());
+ lo_message_add_int32 (reply, r->n_inputs().n_audio());
+ lo_message_add_int32 (reply, r->n_outputs().n_audio());
+ lo_message_add_int32 (reply, r->muted());
+ lo_message_add_int32 (reply, r->soloed());
+ lo_message_add_int32 (reply, r->remote_control_id());
+
+ if (boost::dynamic_pointer_cast<AudioTrack>(r)
+ || boost::dynamic_pointer_cast<MidiTrack>(r)) {
+
+ boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
+ lo_message_add_int32 (reply, t->record_enabled());
+ }
+
+ lo_send_message (lo_message_get_source (msg), "#reply", reply);
+ lo_message_free (reply);
+
+ //Automatically listen to routes listed
+ listen_to_route(r, lo_message_get_source (msg));
+ }
+ }
+
+ // Send end of listing message
+ lo_message reply = lo_message_new ();
+
+ lo_message_add_string (reply, "end_route_list");
+ lo_message_add_int64 (reply, session->frame_rate());
+ lo_message_add_int64 (reply, session->current_end_frame());
+
+ lo_send_message (lo_message_get_source (msg), "#reply", reply);
+
+ lo_message_free (reply);
+
+ ret = 0;
}
return ret;
}
void
+OSC::update_clock (){
+
+}
+
+void
OSC::listen_to_route (boost::shared_ptr<Route> route, lo_address addr)
{
Controllables::iterator x;
@@ -560,8 +639,10 @@
route_exists = true;
/* XXX NEED lo_address_equal() */
+ int res = strcmp(lo_address_get_hostname(rc->address()), lo_address_get_hostname(addr));
- if (rc->address() == addr) {
+ if (res == 0) {
+ cerr << "already listening to route" << endl;
return;
}
}
@@ -572,6 +653,15 @@
OSCControllable* c;
string path;
+
+ if (boost::dynamic_pointer_cast<AudioTrack>(route) || boost::dynamic_pointer_cast<MidiTrack>(route)) {
+
+ boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track>(route);
+
+ path = X_("/route/rec");
+ c = new OSCRouteControllable (addr, path, track->rec_enable_control(), track);
+ controllables.push_back (c);
+ }
path = X_("/route/solo");
c = new OSCRouteControllable (addr, path, route->solo_control(), route);
@@ -584,9 +674,14 @@
path = X_("/route/gain");
c = new OSCRouteControllable (addr, path, route->gain_control(), route);
controllables.push_back (c);
-
+
cerr << "Now have " << controllables.size() << " controllables\n";
+ OSCRouteObserver* o;
+
+ o = new OSCRouteObserver (addr, path, route);
+ observables.push_back (o);
+
/* if there is no existing controllable related to this route, make sure we clean up
if it is ever deleted.
*/
@@ -627,22 +722,51 @@
{
Controllables::iterator x;
- for (x = controllables.begin(); x != controllables.end(); ++x) {
+ for (x = controllables.begin(); x != controllables.end();) {
OSCRouteControllable* rc;
if ((rc = dynamic_cast<OSCRouteControllable*>(*x)) != 0) {
/* XXX NEED lo_address_equal () */
+ if (rc->route() == r && (0 == strcmp(lo_address_get_hostname(rc->address()), lo_address_get_hostname(addr)))){
+ delete *x;
+ x = controllables.erase (x);
+ }
+ else {
+ ++x;
+ }
+ }
+ else {
+ ++x;
+ }
+ }
+
+ Observables::iterator z;
+
+ // Remove the route observers
+ for (z = observables.begin(); z != observables.end();) {
- if (rc->route() == r && rc->address() == addr) {
- controllables.erase (x);
- return;
+ OSCRouteObserver* ro;
+
+ if ((ro = dynamic_cast<OSCRouteObserver*>(*z)) != 0) {
+
+ /* XXX NEED lo_address_equal () */
+ if (ro->route() == r){
+ delete *z;
+ z = observables.erase (z);
}
+ else {
+ ++z;
+ }
}
+ else {
+ ++z;
+ }
}
}
+
// "Application Hook" Handlers //
void
OSC::session_loaded( Session& s ) {
Index: libs/surfaces/osc/osc_controllable.cc
===================================================================
--- libs/surfaces/osc/osc_controllable.cc (revision 8177)
+++ libs/surfaces/osc/osc_controllable.cc (working copy)
@@ -33,14 +33,15 @@
OSCControllable::OSCControllable (lo_address a, const std::string& p, boost::shared_ptr<Controllable> c)
: controllable (c)
- , addr (a)
, path (p)
{
+ addr = lo_address_new (lo_address_get_hostname(a) , lo_address_get_port(a));
c->Changed.connect (changed_connection, MISSING_INVALIDATOR, boost::bind (&OSCControllable::send_change_message, this), OSC::instance());
}
OSCControllable::~OSCControllable ()
{
+ changed_connection.disconnect();
lo_address_free (addr);
}
@@ -93,7 +94,8 @@
/* XXX thread issues */
- std::cerr << "ORC: send " << path << " = " << controllable->get_value() << std::endl;
+ //std::cerr << "ORC: send " << path << " = " << controllable->get_value() << std::endl;
+
lo_send_message (addr, path.c_str(), msg);
lo_message_free (msg);
}
Index: libs/surfaces/osc/osc.h
===================================================================
--- libs/surfaces/osc/osc.h (revision 8177)
+++ libs/surfaces/osc/osc.h (working copy)
@@ -37,6 +37,7 @@
#include "control_protocol/control_protocol.h"
class OSCControllable;
+class OSCRouteObserver;
namespace ARDOUR {
class Session;
@@ -213,10 +214,17 @@
void listen_to_route (boost::shared_ptr<ARDOUR::Route>, lo_address);
void end_listen (boost::shared_ptr<ARDOUR::Route>, lo_address);
void drop_route (boost::weak_ptr<ARDOUR::Route>);
+
+ void route_name_changed (const PBD::PropertyChange&, boost::weak_ptr<ARDOUR::Route> r, lo_address addr);
+
+ void update_clock ();
+
typedef std::list<OSCControllable*> Controllables;
+ typedef std::list<OSCRouteObserver*> Observables;
Controllables controllables;
+ Observables observables;
static OSC* _instance;
};
Index: libs/surfaces/osc/wscript
===================================================================
--- libs/surfaces/osc/wscript (revision 8177)
+++ libs/surfaces/osc/wscript (working copy)
@@ -24,6 +24,7 @@
obj.source = '''
osc.cc
osc_controllable.cc
+ osc_route_observer.cc
interface.cc
'''
obj.export_incdirs = ['.']
|
|
2010-12-05 21:23
|
osc_route_observer.cc (1,980 bytes)
/*
Copyright (C) 2009 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <cstdio> /* for sprintf, sigh */
#include <climits>
#include "boost/lambda/lambda.hpp"
#include "pbd/error.h"
#include "pbd/xml++.h"
#include "ardour/route.h"
#include "osc.h"
#include "osc_route_observer.h"
#define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
using namespace sigc;
using namespace PBD;
using namespace ARDOUR;
OSCRouteObserver::OSCRouteObserver (lo_address a, const std::string& p, boost::shared_ptr<Route> r)
: _route (r)
{
addr = lo_address_new (lo_address_get_hostname(a) , lo_address_get_port(a));
_route->PropertyChanged.connect (changed_connection, MISSING_INVALIDATOR, ui_bind (&OSCRouteObserver::name_changed, this, boost::lambda::_1), OSC::instance());
}
OSCRouteObserver::~OSCRouteObserver ()
{
changed_connection.disconnect();
lo_address_free (addr);
}
void
OSCRouteObserver::name_changed (const PBD::PropertyChange& what_changed)
{
if (!what_changed.contains (ARDOUR::Properties::name)) {
return;
}
if (!_route) {
return;
}
lo_message msg = lo_message_new ();
lo_message_add_int32 (msg, _route->remote_control_id());
lo_message_add_string (msg, _route->name().c_str());
lo_send_message (addr, "/route/name", msg);
lo_message_free (msg);
}
|
|
2010-12-05 21:24
|
osc_route_observer.h (1,501 bytes)
/*
Copyright (C) 2009 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __osc_oscrouteobserver_h__
#define __osc_oscrouteobserver_h__
#include <string>
#include <boost/shared_ptr.hpp>
#include <sigc++/sigc++.h>
#include <lo/lo.h>
#include "pbd/controllable.h"
#include "pbd/stateful.h"
#include "ardour/types.h"
namespace ARDOUR {
class Route;
}
class OSCRouteObserver
{
public:
OSCRouteObserver (lo_address addr, const std::string& path, boost::shared_ptr<ARDOUR::Route>);
~OSCRouteObserver ();
boost::shared_ptr<ARDOUR::Route> route() const { return _route; }
private:
boost::shared_ptr<ARDOUR::Route> _route;
PBD::ScopedConnection changed_connection;
lo_address addr;
std::string path;
void name_changed (const PBD::PropertyChange& what_changed);
};
#endif /* __osc_oscrouteobserver_h__ */
|
|
|
osc_route_observer.cc and osc_route_observer.h should be placed in ardour_source_root/libs/surfaces/osc |
|
|
These patched have been applied to SVN. |
|
|
Issue has been closed automatically, by Trigger Close Plugin. Feel free to re-open with additional information if you think the issue is not resolved. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2010-12-05 21:23 | lincoln | New Issue | |
| 2010-12-05 21:23 | lincoln | File Added: osc-adds-for-ardroid.patch | |
| 2010-12-05 21:23 | lincoln | File Added: osc_route_observer.cc | |
| 2010-12-05 21:24 | lincoln | File Added: osc_route_observer.h | |
| 2010-12-05 21:25 | lincoln | Note Added: 0009549 | |
| 2010-12-06 13:42 | cth103 | cost | => 0.00 |
| 2010-12-06 13:42 | cth103 | Target Version | => 3.0-beta1 |
| 2011-01-10 12:07 | lincoln | Note Added: 0009901 | |
| 2011-01-10 12:07 | lincoln | Status | new => resolved |
| 2011-01-10 12:07 | lincoln | Resolution | open => fixed |
| 2011-01-10 12:07 | lincoln | Assigned To | => lincoln |
| 2020-04-19 20:14 | system | Note Added: 0022289 | |
| 2020-04-19 20:14 | system | Status | resolved => closed |