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:
29
SConstruct
29
SConstruct
@@ -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']:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 +
|
||||
|
||||
@@ -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 ()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
63
libs/surfaces/osc/SConscript
Normal file
63
libs/surfaces/osc/SConscript
Normal 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')))
|
||||
66
libs/surfaces/osc/interface.cc
Normal file
66
libs/surfaces/osc/interface.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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*);
|
||||
};
|
||||
|
||||
}
|
||||
54
libs/surfaces/osc/osc_controllable.cc
Normal file
54
libs/surfaces/osc/osc_controllable.cc
Normal 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;
|
||||
}
|
||||
|
||||
46
libs/surfaces/osc/osc_controllable.h
Normal file
46
libs/surfaces/osc/osc_controllable.h
Normal 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__ */
|
||||
Reference in New Issue
Block a user