From f8d3b1f7a77cbe7bdb04bbc27f4a85ea0ca3e4e5 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 19 Jan 2011 22:05:38 +0000 Subject: Lincoln's OSC clean-ups (#3716). git-svn-id: svn://localhost/ardour2/branches/3.0@8552 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/surfaces/osc/osc.cc | 416 ++++++++++++++------------------ libs/surfaces/osc/osc.h | 26 +- libs/surfaces/osc/osc_route_observer.cc | 55 ++++- libs/surfaces/osc/osc_route_observer.h | 18 +- 4 files changed, 261 insertions(+), 254 deletions(-) (limited to 'libs/surfaces') diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index 8eff8e0e1b..93b56a8a97 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -201,11 +201,10 @@ OSC::start () 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 << "'" <(*x)) != 0) { + delete *x; + x = route_observers.erase (x); + } else { + ++x; + } + } + return 0; } @@ -314,9 +326,10 @@ OSC::register_callbacks() /* this is a special catchall handler */ lo_server_add_method (serv, 0, 0, _catchall, this); - + #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this) + REGISTER_CALLBACK (serv, "/routes/list", "", routes_list); REGISTER_CALLBACK (serv, "/ardour/add_marker", "", add_marker); REGISTER_CALLBACK (serv, "/ardour/access_action", "s", access_action); REGISTER_CALLBACK (serv, "/ardour/loop_toggle", "", loop_toggle); @@ -326,7 +339,7 @@ OSC::register_callbacks() 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/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); @@ -408,6 +421,85 @@ OSC::get_unix_server_url() return url; } +void +OSC::listen_to_route (boost::shared_ptr route, lo_address addr) +{ + /* avoid duplicate listens */ + + for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end(); ++x) { + + OSCRouteObserver* ro; + + if ((ro = dynamic_cast(*x)) != 0) { + + int res = strcmp(lo_address_get_hostname(ro->address()), lo_address_get_hostname(addr)); + + if (ro->route() == route && res == 0) { + return; + } + } + } + + OSCRouteObserver* o = new OSCRouteObserver (route, addr); + route_observers.push_back (o); + + route->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr (route)), this); +} + +void +OSC::drop_route (boost::weak_ptr wr) +{ + boost::shared_ptr r = wr.lock (); + + if (!r) { + return; + } + + for (RouteObservers::iterator x = route_observers.begin(); x != route_observers.end();) { + + OSCRouteObserver* rc; + + if ((rc = dynamic_cast(*x)) != 0) { + + if (rc->route() == r) { + delete *x; + x = route_observers.erase (x); + } else { + ++x; + } + } else { + ++x; + } + } +} + +void +OSC::end_listen (boost::shared_ptr r, lo_address addr) +{ + RouteObservers::iterator x; + + // Remove the route observers + for (x = route_observers.begin(); x != route_observers.end();) { + + OSCRouteObserver* ro; + + if ((ro = dynamic_cast(*x)) != 0) { + + int res = strcmp(lo_address_get_hostname(ro->address()), lo_address_get_hostname(addr)); + + if (ro->route() == r && res == 0) { + delete *x; + x = route_observers.erase (x); + } + else { + ++x; + } + } + else { + ++x; + } + } +} void OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg) @@ -499,19 +591,7 @@ OSC::catchall (const char *path, const char *types, lo_arg **argv, int argc, lo_ 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"; @@ -553,229 +633,31 @@ OSC::catchall (const char *path, const char *types, lo_arg **argv, int argc, lo_ } } - ret = 0; - - } else if (strcmp (path, "/routes/list") == 0) { - - for (int n = 0; n < (int) session->nroutes(); ++n) { - - boost::shared_ptr r = session->route_by_remote_id (n); - - if (r) { - - lo_message reply = lo_message_new (); - - if (boost::dynamic_pointer_cast(r)) { - lo_message_add_string (reply, "AT"); - } else if (boost::dynamic_pointer_cast(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(r) - || boost::dynamic_pointer_cast(r)) { - - boost::shared_ptr t = boost::dynamic_pointer_cast(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; - } + ret = 0; + } return ret; } void -OSC::update_clock (){ - -} - -void -OSC::listen_to_route (boost::shared_ptr route, lo_address addr) +OSC::update_clock () { - Controllables::iterator x; - bool route_exists = false; - - cerr << "listen to route\n"; - - /* avoid duplicate listens */ - - for (x = controllables.begin(); x != controllables.end(); ++x) { - - OSCRouteControllable* rc; - - if ((rc = dynamic_cast(*x)) != 0) { - - if (rc->route() == route) { - route_exists = true; - - /* XXX NEED lo_address_equal() */ - int res = strcmp(lo_address_get_hostname(rc->address()), lo_address_get_hostname(addr)); - - if (res == 0) { - cerr << "already listening to route" << endl; - return; - } - } - } - } - - cerr << "listener binding to signals\n"; - - OSCControllable* c; - string path; - - if (boost::dynamic_pointer_cast(route) || boost::dynamic_pointer_cast(route)) { - - boost::shared_ptr track = boost::dynamic_pointer_cast(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); - controllables.push_back (c); - - path = X_("/route/mute"); - c = new OSCRouteControllable (addr, path, route->mute_control(), route); - controllables.push_back (c); - - 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. - */ - - if (!route_exists) { - route->DropReferences.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::drop_route, this, boost::weak_ptr (route)), this); - } + } +// "Application Hook" Handlers // void -OSC::drop_route (boost::weak_ptr wr) +OSC::session_loaded (Session& s) { - boost::shared_ptr r = wr.lock (); - - if (!r) { - return; - } - - for (Controllables::iterator x = controllables.begin(); x != controllables.end();) { - - OSCRouteControllable* rc; - - if ((rc = dynamic_cast(*x)) != 0) { - if (rc->route() == r) { - delete *x; - x = controllables.erase (x); - } else { - ++x; - } - } else { - ++x; - } - } + lo_address listener = lo_address_new (NULL, "7770"); + lo_send (listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str()); } void -OSC::end_listen (boost::shared_ptr r, lo_address addr) +OSC::session_exported (std::string path, std::string name) { - Controllables::iterator x; - - for (x = controllables.begin(); x != controllables.end();) { - - OSCRouteControllable* rc; - - if ((rc = dynamic_cast(*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();) { - - OSCRouteObserver* ro; - - if ((ro = dynamic_cast(*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 ) { - lo_address listener = lo_address_new( NULL, "7770" ); - lo_send( listener, "/session/loaded", "ss", s.path().c_str(), s.name().c_str() ); -} - -void -OSC::session_exported( std::string path, std::string name ) { - lo_address listener = lo_address_new( NULL, "7770" ); - lo_send( listener, "/session/exported", "ss", path.c_str(), name.c_str() ); + lo_address listener = lo_address_new (NULL, "7770"); + lo_send (listener, "/session/exported", "ss", path.c_str(), name.c_str()); } // end "Application Hook" Handlers // @@ -842,6 +724,72 @@ OSC::current_value (const char */*path*/, const char */*types*/, lo_arg **/*argv return 0; } +void +OSC::routes_list (lo_message msg) +{ + for (int n = 0; n < (int) session->nroutes(); ++n) { + + boost::shared_ptr r = session->route_by_remote_id (n); + + if (r) { + + lo_message reply = lo_message_new (); + + if (boost::dynamic_pointer_cast(r)) { + lo_message_add_string (reply, "AT"); + } else if (boost::dynamic_pointer_cast(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(r) + || boost::dynamic_pointer_cast(r)) { + + boost::shared_ptr t = boost::dynamic_pointer_cast(r); + lo_message_add_int32 (reply, t->record_enabled()); + } + + //Automatically listen to routes listed + listen_to_route(r, lo_message_get_source (msg)); + + lo_send_message (lo_message_get_source (msg), "#reply", reply); + lo_message_free (reply); + } + } + + // 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); +} + +void +OSC::transport_frame (lo_message msg) +{ + framepos_t pos = session->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); +} + int OSC::route_mute (int rid, int yn) { @@ -852,6 +800,7 @@ OSC::route_mute (int rid, int yn) if (r) { r->set_mute (yn, this); } + return 0; } @@ -865,6 +814,7 @@ OSC::route_solo (int rid, int yn) if (r) { r->set_solo (yn, this); } + return 0; } @@ -878,6 +828,7 @@ OSC::route_recenable (int rid, int yn) if (r) { r->set_record_enabled (yn, this); } + return 0; } @@ -946,7 +897,7 @@ OSC::route_set_pan_stereo_width (int rid, float pos) } int -OSC::route_plugin_parameter (int rid,int piid,int par, float val) +OSC::route_plugin_parameter (int rid, int piid, int par, float val) { if (!session) { return -1; @@ -993,7 +944,7 @@ OSC::route_plugin_parameter (int rid,int piid,int par, float val) } int -OSC::route_plugin_parameter_print (int rid,int piid,int par) +OSC::route_plugin_parameter_print (int rid, int piid, int par) { if (!session) { return -1; @@ -1016,7 +967,8 @@ OSC::route_plugin_parameter_print (int rid,int piid,int par) if (!(pi = boost::dynamic_pointer_cast(redi))) { return -1; } - boost::shared_ptr pip=pi->plugin(); + + boost::shared_ptr pip = pi->plugin(); bool ok=false; uint32_t controlid = pip->nth_parameter (par,ok); @@ -1044,7 +996,7 @@ OSC::get_state () { return *(new XMLNode ("OSC")); } - + int OSC::set_state (const XMLNode&, int /*version*/) { diff --git a/libs/surfaces/osc/osc.h b/libs/surfaces/osc/osc.h index cda8a31704..27c2e6ba03 100644 --- a/libs/surfaces/osc/osc.h +++ b/libs/surfaces/osc/osc.h @@ -111,11 +111,27 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI void send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg); void current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg); + + int current_value (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data); + int catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data); static int _catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data); - int current_value (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data); + void routes_list (lo_message msg); + void transport_frame(lo_message msg); +#define PATH_CALLBACK_MSG(name) \ + static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \ + return static_cast(user_data)->cb_ ## name (path, types, argv, argc, data); \ + } \ + int cb_ ## name (const char *, const char *, lo_arg **argv, int argc, void *data) { \ + name (data); \ + return 0; \ + } + + PATH_CALLBACK_MSG(routes_list); + PATH_CALLBACK_MSG(transport_frame); + #define PATH_CALLBACK(name) \ static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \ return static_cast(user_data)->cb_ ## name (path, types, argv, argc, data); \ @@ -210,7 +226,7 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI int route_set_pan_stereo_width (int rid, float percent); int route_plugin_parameter (int rid, int piid,int par, float val); int route_plugin_parameter_print (int rid, int piid,int par); - + void listen_to_route (boost::shared_ptr, lo_address); void end_listen (boost::shared_ptr, lo_address); void drop_route (boost::weak_ptr); @@ -220,11 +236,9 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI void update_clock (); - typedef std::list Controllables; - typedef std::list Observables; + typedef std::list RouteObservers; - Controllables controllables; - Observables observables; + RouteObservers route_observers; static OSC* _instance; }; diff --git a/libs/surfaces/osc/osc_route_observer.cc b/libs/surfaces/osc/osc_route_observer.cc index 3a5a835b5e..1433cd146b 100644 --- a/libs/surfaces/osc/osc_route_observer.cc +++ b/libs/surfaces/osc/osc_route_observer.cc @@ -17,36 +17,57 @@ */ -#include /* for sprintf, sigh */ -#include - #include "boost/lambda/lambda.hpp" -#include "pbd/error.h" -#include "pbd/xml++.h" - #include "ardour/route.h" +#include "ardour/audio_track.h" +#include "ardour/midi_track.h" #include "osc.h" #include "osc_route_observer.h" #define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__)) +using namespace std; using namespace sigc; using namespace PBD; using namespace ARDOUR; +using namespace boost; -OSCRouteObserver::OSCRouteObserver (lo_address a, const std::string& p, boost::shared_ptr r) +OSCRouteObserver::OSCRouteObserver (shared_ptr r, lo_address a) : _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()); + + _route->PropertyChanged.connect (name_changed_connection, MISSING_INVALIDATOR, ui_bind (&OSCRouteObserver::name_changed, this, boost::lambda::_1), OSC::instance()); + + if (dynamic_pointer_cast(_route) || dynamic_pointer_cast(_route)) { + + shared_ptr track = dynamic_pointer_cast(r); + shared_ptr rec_controllable = dynamic_pointer_cast(track->rec_enable_control()); + + rec_controllable->Changed.connect (rec_changed_connection, MISSING_INVALIDATOR, bind (&OSCRouteObserver::send_change_message, this, X_("/route/rec"), track->rec_enable_control()), OSC::instance()); + } + + shared_ptr mute_controllable = dynamic_pointer_cast(_route->mute_control()); + mute_controllable->Changed.connect (mute_changed_connection, MISSING_INVALIDATOR, bind (&OSCRouteObserver::send_change_message, this, X_("/route/mute"), _route->mute_control()), OSC::instance()); + + shared_ptr solo_controllable = dynamic_pointer_cast(_route->solo_control()); + solo_controllable->Changed.connect (solo_changed_connection, MISSING_INVALIDATOR, bind (&OSCRouteObserver::send_change_message, this, X_("/route/solo"), _route->solo_control()), OSC::instance()); + + shared_ptr gain_controllable = dynamic_pointer_cast(_route->gain_control()); + gain_controllable->Changed.connect (gain_changed_connection, MISSING_INVALIDATOR, bind (&OSCRouteObserver::send_change_message, this, X_("/route/gain"), _route->gain_control()), OSC::instance()); } OSCRouteObserver::~OSCRouteObserver () { - changed_connection.disconnect(); + name_changed_connection.disconnect(); + rec_changed_connection.disconnect(); + mute_changed_connection.disconnect(); + solo_changed_connection.disconnect(); + gain_changed_connection.disconnect(); + lo_address_free (addr); } @@ -69,3 +90,19 @@ OSCRouteObserver::name_changed (const PBD::PropertyChange& what_changed) lo_send_message (addr, "/route/name", msg); lo_message_free (msg); } + +void +OSCRouteObserver::send_change_message (string path, shared_ptr controllable) +{ + lo_message msg = lo_message_new (); + + lo_message_add_int32 (msg, _route->remote_control_id()); + lo_message_add_float (msg, (float) controllable->get_value()); + + /* XXX thread issues */ + + //std::cerr << "ORC: send " << path << " = " << controllable->get_value() << std::endl; + + lo_send_message (addr, path.c_str(), msg); + lo_message_free (msg); +} diff --git a/libs/surfaces/osc/osc_route_observer.h b/libs/surfaces/osc/osc_route_observer.h index 779640af40..d491c8bf1b 100644 --- a/libs/surfaces/osc/osc_route_observer.h +++ b/libs/surfaces/osc/osc_route_observer.h @@ -29,27 +29,31 @@ #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); + OSCRouteObserver (boost::shared_ptr, lo_address addr); ~OSCRouteObserver (); - boost::shared_ptr route() const { return _route; } + boost::shared_ptr route () const { return _route; } + lo_address address() const { return addr; }; private: boost::shared_ptr _route; + //boost::shared_ptr _controllable; + + PBD::ScopedConnection name_changed_connection; + PBD::ScopedConnection rec_changed_connection; + PBD::ScopedConnection mute_changed_connection; + PBD::ScopedConnection solo_changed_connection; + PBD::ScopedConnection gain_changed_connection; - PBD::ScopedConnection changed_connection; lo_address addr; std::string path; void name_changed (const PBD::PropertyChange& what_changed); + void send_change_message (std::string path, boost::shared_ptr controllable); }; #endif /* __osc_oscrouteobserver_h__ */ -- cgit v1.2.3