OSC becomes a control protocol object; make ardev_common.sh(.in) look for surfaces in the right place(s)

git-svn-id: svn://localhost/ardour2/branches/3.0@4411 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis
2009-01-15 22:09:23 +00:00
parent 13e40db5e5
commit 16556bb182
12 changed files with 657 additions and 124 deletions

View File

@@ -45,7 +45,6 @@ opts.AddOptions(
BoolOption('EXTRA_WARN', 'Compile with -Wextra, -ansi, and -pedantic. Might break compilation. For pedants', 0),
BoolOption('FREESOUND', 'Include Freesound database lookup', 0),
BoolOption('FPU_OPTIMIZATION', 'Build runtime checked assembler code', 1),
BoolOption('LIBLO', 'Compile with support for liblo library', 1),
BoolOption('NLS', 'Set to turn on i18n support', 1),
PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
BoolOption('SURFACES', 'Build support for control surfaces', 1),
@@ -867,10 +866,6 @@ if env['EXTRA_WARN']:
env.Append(CXXFLAGS="-ansi")
# env.Append(CFLAGS="-iso")
if env['LIBLO']:
env.Append(CCFLAGS="-DHAVE_LIBLO")
#
# fix scons nitpickiness on APPLE
#
@@ -998,16 +993,17 @@ libraries['boost'] = conf.Finish ()
#
# Check for liblo
if env['LIBLO']:
libraries['lo'] = LibraryInfo ()
prep_libcheck(env, libraries['lo'])
libraries['lo'] = LibraryInfo ()
prep_libcheck(env, libraries['lo'])
conf = Configure (libraries['lo'])
if conf.CheckLib ('lo', 'lo_server_new') == False:
print "liblo does not appear to be installed."
sys.exit (1)
libraries['lo'] = conf.Finish ()
conf = Configure (libraries['lo'])
if conf.CheckLib ('lo', 'lo_server_new') == False:
print "liblo does not appear to be installed."
env['HAVE_LIBLO'] = False
else:
env['HAVE_LIBLO'] = True
libraries['lo'] = conf.Finish ()
#
# Check for dmalloc
@@ -1270,7 +1266,7 @@ else:
#
# * always build the LGPL control protocol lib, since we link against it from libardour
# * ditto for generic MIDI
# * ditto for generic MIDI and OSC
# * tranzport & wiimote check whether they should build internally, but we need them here
# so that they are included in the tarball
#
@@ -1280,7 +1276,8 @@ surface_subdirs = [ 'libs/surfaces/control_protocol',
'libs/surfaces/tranzport',
'libs/surfaces/mackie',
'libs/surfaces/powermate',
'libs/surfaces/wiimote'
'libs/surfaces/wiimote',
'libs/surfaces/osc'
]
if env['SURFACES']:

View File

@@ -3,6 +3,7 @@ cd `dirname "$0"`/..
#export G_DEBUG=fatal_criticals
export ARDOUR_PATH=gtk2_ardour/icons:gtk2_ardour/pixmaps:gtk2_ardour:.
export ARDOUR_SURFACES_PATH=libs/surfaces/osc:libs/surfaces/generic_midi:libs/surfaces/tranzport:libs/surfaces/powermate
export ARDOUR_DATA_PATH=gtk2_ardour:.
if test -d $HOME/gtk/inst ; then
echo USING NEW CLEARLOOKS

View File

@@ -178,7 +178,6 @@ version.cc
arch_specific_objects = [ ]
osc_files = [ 'osc.cc' ]
vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
lv2_files = [ 'lv2_plugin.cc' ]
audiounit_files = [ 'audio_unit.cc' ]
@@ -194,9 +193,6 @@ if ardour['LV2']:
extra_sources += lv2_files
ardour.Append(CCFLAGS="-DHAVE_SLV2")
if ardour['LIBLO']:
extra_sources += osc_files
ardour.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
ardour.Append(CXXFLAGS="-DDATA_DIR=\\\"" + os.path.join (final_prefix, 'share') + "\\\"")
ardour.Append(CXXFLAGS="-DMODULE_DIR=\\\"" + os.path.join (final_prefix, env['LIBDIR']) + "\\\"")
@@ -362,9 +358,6 @@ else:
if ardour['LV2']:
ardour.Merge ([ libraries['slv2'] ])
if ardour['LIBLO']:
ardour.Merge ([ libraries['lo'] ])
if ardour['COREAUDIO'] or ardour['AUDIOUNITS']:
ardour.Merge ([ libraries['appleutility'] ])
@@ -418,7 +411,6 @@ env.Alias('tarball', env.Distribute (env['DISTTREE'],
[ 'sse_functions_xmm.cc', 'sse_functions.s', 'sse_functions_64bit.s' ] +
[ 'rb_effect.cc', 'st_stretch.cc', 'st_pitch.cc' ] +
ardour_files +
osc_files +
vst_files +
coreaudio_files +
audiounit_files +

View File

@@ -67,10 +67,6 @@
#include <ardour/audioengine.h>
#include <ardour/filesystem_paths.h>
#ifdef HAVE_LIBLO
#include <ardour/osc.h>
#endif
#include <ardour/mix.h>
#include <ardour/runtime_functions.h>
@@ -84,10 +80,6 @@ ARDOUR::Configuration* ARDOUR::Config = 0;
ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
ARDOUR::AudioLibrary* ARDOUR::Library = 0;
#ifdef HAVE_LIBLO
ARDOUR::OSC* ARDOUR::osc = 0;
#endif
using namespace ARDOUR;
using namespace std;
using namespace PBD;
@@ -111,26 +103,6 @@ mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
sigc::signal<void,std::string> ARDOUR::BootMessage;
#ifdef HAVE_LIBLO
static int
setup_osc ()
{
/* no real cost to creating this object, and it avoids
conditionals anywhere that uses it
*/
osc = new OSC (Config->get_osc_port());
if (Config->get_use_osc ()) {
BootMessage (_("Starting OSC"));
return osc->start ();
} else {
return 0;
}
}
#endif
int
ARDOUR::setup_midi ()
{
@@ -341,11 +313,6 @@ ARDOUR::init (bool use_vst, bool try_optimization)
Profile = new RuntimeProfile;
#ifdef HAVE_LIBLO
if (setup_osc ()) {
return -1;
}
#endif
#ifdef VST_SUPPORT
if (Config->get_use_vst() && fst_init ()) {

View File

@@ -83,10 +83,6 @@
#include <ardour/analyser.h>
#include <ardour/bundle.h>
#ifdef HAVE_LIBLO
#include <ardour/osc.h>
#endif
#include "i18n.h"
using namespace std;
@@ -728,15 +724,6 @@ Session::when_engine_running ()
BootMessage (_("Connect to engine"));
_engine.set_session (this);
#ifdef HAVE_LIBLO
/* and to OSC */
BootMessage (_("OSC startup"));
osc->set_session (*this);
#endif
}
void

View File

@@ -9,7 +9,7 @@ Import('env final_prefix install_prefix final_config_prefix libraries i18n')
genericmidi = env.Clone()
#
# this defines the version number of libardour_genericmidi
# this defines the translation domain of libardour_genericmidi
#
domain = 'ardour_genericmidi'

View File

@@ -0,0 +1,63 @@
# -*- python -*-
import os
import os.path
import glob
Import('env final_prefix install_prefix final_config_prefix libraries i18n')
osc = env.Clone()
#
# this defines the translation domain of libardour_osc
#
domain = 'ardour_osc'
osc.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
osc.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
osc.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
osc.Append(PACKAGE = domain)
osc.Append(POTFILE = domain + '.pot')
osc_files=Split("""
osc.cc
osc_controllable.cc
interface.cc
""")
osc.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
osc.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
osc.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
osc.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
osc.Append(CPPPATH = libraries['jack'].get('CPPPATH', []))
osc.Merge ([
libraries['lo'],
libraries['midi++2'],
libraries['evoral'],
libraries['ardour'],
libraries['ardour_cp'],
libraries['pbd'],
libraries['sigc2'],
libraries['xml'],
libraries['glib2'],
libraries['glibmm2']
])
libardour_osc = osc.SharedLibrary('ardour_osc', osc_files)
if osc['HAVE_LIBLO']:
Default(libardour_osc)
if env['NLS']:
i18n (osc, osc_files, env)
env.Alias('install', env.Install(os.path.join(install_prefix,
env['LIBDIR'],
'ardour3',
'surfaces'),
libardour_osc))
env.Alias('tarball', env.Distribute (env['DISTTREE'],
[ 'SConscript' ] +
osc_files +
glob.glob('po/*.po') + glob.glob('*.h')))

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2006 Paul Davis
* Copyright (C) 2007 Michael Taht
*
* 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 <control_protocol/control_protocol.h>
#include "osc.h"
using namespace ARDOUR;
ControlProtocol*
new_osc_protocol (ControlProtocolDescriptor* descriptor, Session* s)
{
OSC* osc = new OSC (*s, Config->get_osc_port());
osc->set_active (true);
return osc;
}
void
delete_osc_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
{
delete cp;
}
bool
probe_osc_protocol (ControlProtocolDescriptor* descriptor)
{
return true; // we can always do OSC
}
static ControlProtocolDescriptor osc_descriptor = {
name : "Open Sound Control (OSC)",
id : "uri://ardour.org/surfaces/osc:0",
ptr : 0,
module : 0,
mandatory : 1,
supports_feedback : true,
probe : probe_osc_protocol,
initialize : new_osc_protocol,
destroy : delete_osc_protocol
};
extern "C" {
ControlProtocolDescriptor*
protocol_descriptor () {
return &osc_descriptor;
}
}

View File

@@ -33,20 +33,23 @@
#include <pbd/pthread_utils.h>
#include <pbd/file_utils.h>
#include <pbd/filesystem.h>
#include <pbd/failed_constructor.h>
#include <ardour/osc.h>
#include <ardour/session.h>
#include <ardour/route.h>
#include <ardour/audio_track.h>
#include <ardour/midi_track.h>
#include <ardour/dB.h>
#include <ardour/filesystem_paths.h>
#include "osc.h"
#include "i18n.h"
using namespace ARDOUR;
using namespace sigc;
using namespace std;
static void error_callback(int num, const char *m, const char *path)
{
#ifdef DEBUG
@@ -54,13 +57,61 @@ static void error_callback(int num, const char *m, const char *path)
#endif
}
OSC::OSC (uint32_t port)
: _port(port)
OSC::OSC (Session& s, uint32_t port)
: ControlProtocol (s, "OSC")
, _port(port)
{
_shutdown = false;
_osc_server = 0;
_osc_unix_server = 0;
_osc_thread = 0;
_namespace_root = "/ardour";
_send_route_changes = true;
// "Application Hooks"
session_loaded (s);
session->Exported.connect( mem_fun( *this, &OSC::session_exported ) );
/* catch up with existing routes */
boost::shared_ptr<Session::RouteList> rl = session->get_routes ();
route_added (*(rl.get()));
// session->RouteAdded.connect (mem_fun (*this, &OSC::route_added));
}
OSC::~OSC()
{
stop ();
}
int
OSC::set_active (bool yn)
{
if (yn) {
return start ();
} else {
return stop ();
}
}
bool
OSC::get_active () const
{
return _osc_server != 0;
}
int
OSC::set_feedback (bool yn)
{
_send_route_changes = yn;
return 0;
}
bool
OSC::get_feedback () const
{
return _send_route_changes;
}
int
@@ -162,11 +213,6 @@ OSC::stop ()
return 0;
}
OSC::~OSC()
{
stop ();
}
void
OSC::register_callbacks()
{
@@ -183,6 +229,10 @@ OSC::register_callbacks()
}
serv = srvs[i];
/* 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)
@@ -416,20 +466,217 @@ OSC::osc_receiver()
}
void
OSC::set_session (Session& s)
OSC::current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg)
{
session = &s;
session->GoingAway.connect (mem_fun (*this, &OSC::session_going_away));
// "Application Hooks"
session_loaded( s );
session->Exported.connect( mem_fun( *this, &OSC::session_exported ) );
char* subpath;
subpath = (char*) malloc (len-15+1);
memcpy (subpath, path, len-15);
subpath[len-15] = '\0';
send_current_value (subpath, argv, argc, msg);
free (subpath);
}
void
OSC::session_going_away ()
OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg)
{
session = 0;
if (!session) {
return;
}
lo_message reply = lo_message_new ();
boost::shared_ptr<Route> r;
int id;
lo_message_add_string (reply, path);
if (argc == 0) {
lo_message_add_string (reply, "bad syntax");
} else {
id = argv[0]->i;
r = session->route_by_remote_id (id);
if (!r) {
lo_message_add_string (reply, "not found");
} else {
if (strcmp (path, "/routes/state") == 0) {
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());
} else if (strcmp (path, "/routes/mute") == 0) {
lo_message_add_int32 (reply, (float) r->muted());
} else if (strcmp (path, "/routes/solo") == 0) {
lo_message_add_int32 (reply, r->soloed());
}
}
}
lo_send_message (lo_message_get_source (msg), "#reply", reply);
lo_message_free (reply);
}
int
OSC::_catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data)
{
return ((OSC*)user_data)->catchall (path, types, argv, argc, data);
}
int
OSC::catchall (const char *path, const char *types, lo_arg **argv, int argc, lo_message msg)
{
size_t len;
int ret = 1; /* unhandled */
cerr << "Received a message, path = " << path << " types = \""
<< (types ? types : "NULL") << '"' << endl;
/* 15 for /#current_value plus 2 for /<path> */
len = strlen (path);
if (len >= 17 && !strcmp (&path[len-15], "/#current_value")) {
current_value_query (path, len, argv, argc, msg);
ret = 0;
} else if (strcmp (path, "/routes/listen") == 0) {
cerr << "set up listener\n";
lo_message reply = lo_message_new ();
if (argc > 0) {
int id = argv[0]->i;
boost::shared_ptr<Route> r = session->route_by_remote_id (id);
if (!r) {
lo_message_add_string (reply, "not found");
cerr << "no such route\n";
} else {
ListenerPair listener;
listener.first = r.get();
listener.second = lo_message_get_source (msg);
cerr << "add listener\n";
listen_to_route (listener);
lo_message_add_string (reply, "0");
}
} else {
lo_message_add_string (reply, "syntax error");
}
lo_send_message (lo_message_get_source (msg), "#reply", reply);
lo_message_free (reply);
} else if (strcmp (path, "/routes/ignore") == 0) {
if (argc > 0) {
int id = argv[0]->i;
boost::shared_ptr<Route> r = session->route_by_remote_id (id);
if (r) {
ListenerPair listener;
listener.first = r.get();
listener.second = lo_message_get_source (msg);
drop_listener_pair (listener);
}
}
}
return ret;
}
void
OSC::route_added (Session::RouteList& rl)
{
}
void
OSC::listen_to_route (const ListenerPair& lp)
{
Listeners::iterator x;
bool route_exists = false;
cerr << "listen to route\n";
/* check existing listener pairs to avoid duplicate listens */
for (x = listeners.begin(); x != listeners.end(); ++x) {
if ((*x)->route == lp.first) {
route_exists = true;
if ((*x)->addr == lp.second ) {
return;
}
}
}
Listener* l = new Listener (lp.first, lp.second);
cerr << "listener binding to signals\n";
l->connections.push_back (lp.first->solo_changed.connect (bind (mem_fun (*this, &OSC::route_changed), RouteSolo, lp.first, lp.second)));
l->connections.push_back (lp.first->mute_changed.connect (bind (mem_fun (*this, &OSC::route_changed), RouteMute, lp.first, lp.second)));
l->connections.push_back (lp.first->gain_control()->Changed.connect (bind (mem_fun (*this, &OSC::route_changed_deux), RouteGain, lp.first, lp.second)));
if (!route_exists) {
l->route->GoingAway.connect (bind (mem_fun (*this, &OSC::drop_listeners_by_route), l->route));
}
listeners.push_back (l);
}
void
OSC::drop_listeners_by_route (Route* r)
{
Listeners::iterator x;
for (x = listeners.begin(); x != listeners.end();) {
if ((*x)->route == r) {
delete *x;
x = listeners.erase (x);
} else {
++x;
}
}
}
void
OSC::drop_listener_pair (const ListenerPair& lp)
{
Listeners::iterator x;
for (x = listeners.begin(); x != listeners.end(); ++x) {
if ((*x)->route == lp.first && (*x)->addr == lp.second) {
listeners.erase (x);
return;
}
}
}
// "Application Hook" Handlers //
@@ -445,6 +692,61 @@ OSC::session_exported( std::string path, std::string name ) {
lo_send( listener, "/session/exported", "ss", path.c_str(), name.c_str() );
}
void
OSC::set_send_route_changes (bool yn)
{
_send_route_changes = yn;
}
void
OSC::route_changed (void* src, RouteChangeType what, Route* r, lo_address addr)
{
route_changed_deux (what, r, addr);
}
void
OSC::route_changed_deux (RouteChangeType what, Route* r, lo_address addr)
{
if (!_send_route_changes) {
return;
}
string prefix = _namespace_root;
int ret;
switch (what) {
case OSC::RouteSolo:
prefix += "/changed/route/solo";
ret = lo_send (addr, prefix.c_str(), "ii", r->remote_control_id(), (int) r->soloed());
break;
case OSC::RouteMute:
prefix += "/changed/route/mute";
ret = lo_send (addr, prefix.c_str(), "ii", r->remote_control_id(), (int) r->muted());
break;
case OSC::RouteGain:
prefix += "/changed/route/gain";
ret = lo_send (addr, prefix.c_str(), "if", r->remote_control_id(), r->effective_gain());
default:
error << "OSC: unhandled route change\n";
return;
}
if (ret < 0) {
ListenerPair lp;
lp.first = r;
lp.second = addr;
cerr << "Error sending to listener ... dropping\n";
drop_listener_pair (lp);
}
}
// end "Application Hook" Handlers //
/* path callbacks */
@@ -465,38 +767,38 @@ OSC::current_value (const char *path, const char *types, lo_arg **argv, int argc
const char *retpath = argv[2]->s;
if (strcmp (argv[0]->s, "transport_frame")) {
if (strcmp (argv[0]->s, "transport_frame") == 0) {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
} else if (strcmp (argv[0]->s, "transport_speed")) {
} else if (strcmp (argv[0]->s, "transport_speed") == 0) {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
} else if (strcmp (argv[0]->s, "transport_locked") == 0) {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
} else if (strcmp (argv[0]->s, "punch_in") == 0) {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
} else if (strcmp (argv[0]->s, "punch_out") == 0) {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
} else if (strcmp (argv[0]->s, "transport_locked")) {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
} else if (strcmp (argv[0]->s, "punch_in") {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
} else if (strcmp (argv[0]->s, "punch_out") {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
} else if (strcmp (argv[0]->s, "rec_enable") {
} else if (strcmp (argv[0]->s, "rec_enable") == 0) {
if (session) {
lo_send (addr, retpath, "i", session->transport_frame());
}
@@ -572,6 +874,18 @@ OSC::route_set_gain_dB (int rid, float dB)
if (r) {
r->set_gain (dB_to_coefficient (dB), this);
}
return 0;
}
XMLNode&
OSC::get_state ()
{
return *(new XMLNode ("OSC"));
}
int
OSC::set_state (const XMLNode&)
{
return 0;
}

View File

@@ -30,20 +30,32 @@
#include <sigc++/sigc++.h>
#include <ardour/types.h>
#include <control_protocol/basic_ui.h>
#include <ardour/session.h>
#include <control_protocol/control_protocol.h>
namespace ARDOUR {
class Session;
class Route;
class OSC : public BasicUI, public sigc::trackable
class Session;
class Route;
class OSC : public ControlProtocol
{
public:
OSC (uint32_t port);
OSC (Session&, uint32_t port);
virtual ~OSC();
void set_session (ARDOUR::Session&);
XMLNode& get_state ();
int set_state (const XMLNode&);
int set_active (bool yn);
bool get_active () const;
int set_feedback (bool yn);
bool get_feedback () const;
void set_namespace_root (std::string);
bool send_route_changes () const { return _send_route_changes; }
void set_send_route_changes (bool yn);
int start ();
int stop ();
@@ -55,6 +67,8 @@ class OSC : public BasicUI, public sigc::trackable
lo_server _osc_unix_server;
std::string _osc_unix_socket_path;
std::string _osc_url_file;
std::string _namespace_root;
bool _send_route_changes;
pthread_t _osc_thread;
int _request_pipe[2];
@@ -68,16 +82,31 @@ class OSC : public BasicUI, public sigc::trackable
void register_callbacks ();
void session_going_away ();
void route_added (ARDOUR::Session::RouteList&);
// Handlers for "Application Hook" signals
void session_loaded( ARDOUR::Session& );
void session_exported( std::string, std::string );
void session_loaded (ARDOUR::Session&);
void session_exported (std::string, std::string);
enum RouteChangeType {
RouteSolo,
RouteMute,
RouteGain
};
void route_changed (void* ignored, RouteChangeType, ARDOUR::Route*, lo_address);
void route_changed_deux (RouteChangeType, ARDOUR::Route*, lo_address);
// end "Application Hook" handles
std::string get_server_url ();
std::string get_unix_server_url ();
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 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);
#define PATH_CALLBACK(name) \
@@ -143,6 +172,23 @@ class OSC : public BasicUI, public sigc::trackable
int route_recenable (int rid, int yn);
int route_set_gain_abs (int rid, float level);
int route_set_gain_dB (int rid, float dB);
struct Listener {
Route* route;
lo_address addr;
std::vector<sigc::connection> connections;
Listener (Route* r, lo_address a) : route (r), addr (a) {}
};
typedef std::pair<Route*, lo_address> ListenerPair;
typedef std::list<Listener*> Listeners;
Listeners listeners;
void listen_to_route (const ListenerPair&);
void drop_listener_pair (const ListenerPair&);
void drop_listeners_by_route (Route*);
};
}

View File

@@ -0,0 +1,54 @@
/*
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 <pbd/error.h>
#include <pbd/xml++.h>
#include "osc_controllable.h"
using namespace sigc;
using namespace PBD;
using namespace ARDOUR;
OSCControllable::OSCControllable (lo_address a, Controllable& c)
: controllable (c)
, addr (a)
{
}
OSCControllable::~OSCControllable ()
{
lo_address_free (addr);
}
XMLNode&
OSCControllable::get_state ()
{
XMLNode& root (controllable.get_state());
return root;
}
int
OSCControllable::set_state (const XMLNode& node)
{
return 0;
}

View File

@@ -0,0 +1,46 @@
/*
Copyright (C) 1998-2006 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_osccontrollable_h__
#define __osc_osccontrollable_h__
#include <string>
#include <sigc++/sigc++.h>
#include <lo/lo.h>
#include <pbd/controllable.h>
#include <pbd/stateful.h>
#include <ardour/types.h>
class OSCControllable : public PBD::Stateful
{
public:
OSCControllable (lo_address addr, PBD::Controllable&);
virtual ~OSCControllable ();
XMLNode& get_state ();
int set_state (const XMLNode& node);
private:
PBD::Controllable& controllable;
lo_address addr;
};
#endif /* __osc_osccontrollable_h__ */