View Issue Details

IDProjectCategoryView StatusLast Update
0003587ardourfeaturespublic2020-04-19 20:14
Reporterlincoln Assigned Tolincoln  
PrioritynormalSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
Target Version3.0-beta1 
Summary0003587: OSC modifications for Ardroid
DescriptionArdroid 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.
TagsNo tags attached.

Activities

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 = ['.']
osc-adds-for-ardroid.patch (10,926 bytes)   

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);
}
osc_route_observer.cc (1,980 bytes)   

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.h (1,501 bytes)   

lincoln

2010-12-05 21:25

reporter   ~0009549

osc_route_observer.cc and osc_route_observer.h should be placed in ardour_source_root/libs/surfaces/osc

lincoln

2011-01-10 12:07

reporter   ~0009901

These patched have been applied to SVN.

system

2020-04-19 20:14

developer   ~0022289

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.

Issue History

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