summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-12-31 23:43:47 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-12-31 23:43:47 +0000
commit6c717a56e28ebc67bcf041a1ee9887d46700a0e7 (patch)
treefea823393486d493841d899345cf619ad2f31ca9 /libs
parente00506b0ad7a40f8e876542e40ac85ab1979adb5 (diff)
new PBD::ControllableDescriptor class to encapsulate parsing of binding URIs and speed up lookup at runtime
git-svn-id: svn://localhost/ardour2/branches/3.0@6427 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/session.h3
-rw-r--r--libs/ardour/session_state.cc146
-rw-r--r--libs/pbd/controllable_descriptor.cc150
-rw-r--r--libs/pbd/pbd/controllable_descriptor.h83
-rw-r--r--libs/pbd/wscript1
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc11
-rw-r--r--libs/surfaces/generic_midi/midicontrollable.cc49
-rw-r--r--libs/surfaces/generic_midi/midicontrollable.h15
8 files changed, 346 insertions, 112 deletions
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 6f695e4755..de2dbaa149 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -64,6 +64,7 @@ namespace MIDI {
namespace PBD {
class Controllable;
+ class ControllableDescriptor;
}
namespace Evoral {
@@ -769,7 +770,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
/* Controllables */
boost::shared_ptr<PBD::Controllable> controllable_by_id (const PBD::ID&);
- boost::shared_ptr<PBD::Controllable> controllable_by_rid_and_name (uint32_t, const char* const);
+ boost::shared_ptr<PBD::Controllable> controllable_by_descriptor (const PBD::ControllableDescriptor&);
void add_controllable (boost::shared_ptr<PBD::Controllable>);
void remove_controllable (PBD::Controllable*);
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 3c8fe86c13..3533e48956 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -57,6 +57,7 @@
#include "midi++/port.h"
#include "pbd/boost_debug.h"
+#include "pbd/controllable_descriptor.h"
#include "pbd/enumwriter.h"
#include "pbd/error.h"
#include "pbd/pathscanner.h"
@@ -2680,89 +2681,114 @@ Session::controllable_by_id (const PBD::ID& id)
}
boost::shared_ptr<Controllable>
-Session::controllable_by_rid_and_name (uint32_t rid, const char* const what)
+Session::controllable_by_descriptor (const ControllableDescriptor& desc)
{
boost::shared_ptr<Controllable> c;
- boost::shared_ptr<Route> r = route_by_remote_id (rid);
+ boost::shared_ptr<Route> r;
+
+ switch (desc.top_level_type()) {
+ case ControllableDescriptor::NamedRoute:
+ {
+ std::string str = desc.top_level_name();
+ if (str == "master") {
+ r = _master_out;
+ } else if (str == "control" || str == "listen") {
+ r = _control_out;
+ } else {
+ r = route_by_name (desc.top_level_name());
+ }
+ break;
+ }
+
+ case ControllableDescriptor::RemoteControlID:
+ r = route_by_remote_id (desc.rid());
+ break;
+ }
if (!r) {
return c;
}
- if (strncmp (what, "gain", 4) == 0) {
+ switch (desc.subtype()) {
+ case ControllableDescriptor::Gain:
c = r->gain_control ();
- } else if (strncmp (what, "solo", 4) == 0) {
+ break;
+ case ControllableDescriptor::Solo:
c = r->solo_control();
- } else if (strncmp (what, "mute", 4) == 0) {
- c = r->mute_control();
- } else if (strncmp (what, "pan", 3) == 0) {
-
- /* XXX pan control */
-
- } else if (strncmp (what, "plugin", 6) == 0) {
-
- /* parse to identify plugin & parameter */
-
- uint32_t plugin;
- uint32_t parameter_index;
+ break;
- if (sscanf (what, "plugin%" PRIu32 ":%" PRIu32, &plugin, &parameter_index) == 2) {
-
- /* revert to zero based counting */
-
- if (plugin > 0) {
- --plugin;
- }
-
- if (parameter_index > 0) {
- --parameter_index;
- }
-
- boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
+ case ControllableDescriptor::Mute:
+ c = r->mute_control();
+ break;
- if (p) {
- c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
- p->data().control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
- }
+ case ControllableDescriptor::Recenable:
+ {
+ boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
+
+ if (t) {
+ c = t->rec_enable_control ();
}
+ break;
+ }
- } else if (strncmp (what, "send", 4) == 0) {
-
- /* parse to identify send & property */
+ case ControllableDescriptor::Pan:
+ /* XXX pan control */
+ break;
- uint32_t send;
- char property[64];
+ case ControllableDescriptor::Balance:
+ /* XXX simple pan control */
+ break;
- if (sscanf (what, "send%" PRIu32 ":%63s", &send, property) == 2) {
+ case ControllableDescriptor::PluginParameter:
+ {
+ uint32_t plugin = desc.target (0);
+ uint32_t parameter_index = desc.target (1);
- /* revert to zero-based counting */
-
- if (send > 0) {
- --send;
- }
+ /* revert to zero based counting */
+
+ if (plugin > 0) {
+ --plugin;
+ }
+
+ if (parameter_index > 0) {
+ --parameter_index;
+ }
- boost::shared_ptr<Processor> p = r->nth_send (send);
+ boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
+
+ if (p) {
+ c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
+ p->data().control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
+ }
+ break;
+ }
- if (p) {
- boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
+ case ControllableDescriptor::SendGain:
+ {
+ uint32_t send = desc.target (0);
- if (strcmp (property, "gain") == 0) {
- boost::shared_ptr<Amp> a = s->amp();
- if (a) {
- c = s->amp()->gain_control();
- }
- }
- /* XXX pan control */
- }
+ /* revert to zero-based counting */
+
+ if (send > 0) {
+ --send;
}
- } else if (strncmp (what, "recenable", 9) == 0) {
-
- boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
+ boost::shared_ptr<Processor> p = r->nth_send (send);
+
+ if (p) {
+ boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
+ boost::shared_ptr<Amp> a = s->amp();
- if (t) {
- c = t->rec_enable_control ();
+ if (a) {
+ c = s->amp()->gain_control();
+ }
}
+ break;
+ }
+
+ default:
+ /* relax and return a null pointer */
+ break;
}
return c;
diff --git a/libs/pbd/controllable_descriptor.cc b/libs/pbd/controllable_descriptor.cc
new file mode 100644
index 0000000000..2f84d706b4
--- /dev/null
+++ b/libs/pbd/controllable_descriptor.cc
@@ -0,0 +1,150 @@
+/*
+ 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 "pbd/controllable_descriptor.h"
+#include "pbd/strsplit.h"
+#include "pbd/convert.h"
+
+using namespace std;
+using namespace PBD;
+
+int
+ControllableDescriptor::set (const std::string& str)
+{
+ string::size_type first_space = str.find_first_of (" ");
+
+ if (first_space == string::npos) {
+ return -1;
+ }
+
+ string front = str.substr (0, first_space);
+ string back = str.substr (first_space);
+
+ vector<string> path;
+ split (front, path, '/');
+
+ if (path.size() < 2) {
+ return -1;
+ }
+
+ vector<string> rest;
+ split (back, rest, ' ');
+
+ if (rest.size() < 1) {
+ return -1;
+ }
+
+ cerr << "Path: " << endl;
+ for (vector<string>::iterator x = path.begin(); x != path.end(); ++x) {
+ cerr << '[' << (*x) << "] ";
+ }
+ cerr << endl;
+
+ cerr << "Rest: " << endl;
+ for (vector<string>::iterator x = rest.begin(); x != rest.end(); ++x) {
+ cerr << '[' << (*x) << "] ";
+ }
+ cerr << endl;
+
+ if (path[0] == "route" || path[0] == "rid") {
+
+ _top_level_type = RemoteControlID;
+
+ if (rest[0][0] == 'B') {
+ _banked = true;
+ _rid = atoi (rest[0].substr (1));
+ } else if (isdigit (rest[0][0])) {
+ _banked = false;
+ _rid = atoi (rest[0]);
+ } else {
+ return -1;
+ }
+
+ } else if (path[0] == "bus" || path[0] == "track") {
+
+ _top_level_type = NamedRoute;
+ _top_level_name = rest[0];
+ }
+
+ if (path[1] == "gain") {
+ _subtype = Gain;
+
+ } else if (path[1] == "solo") {
+ _subtype = Solo;
+
+ } else if (path[1] == "mute") {
+ _subtype = Mute;
+
+ } else if (path[1] == "recenable") {
+ _subtype = Recenable;
+
+ } else if (path[1] == "balance") {
+ _subtype = Balance;
+
+ } else if (path[1] == "pan") {
+ _subtype = Pan;
+ _target.push_back (atoi (rest[1]));
+
+ } else if (path[1] == "plugin") {
+ if (path.size() == 3 && rest.size() == 3) {
+ if (path[2] == "parameter") {
+ _subtype = PluginParameter;
+ _target.push_back (atoi (rest[1]));
+ _target.push_back (atoi (rest[2]));
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ } else if (path[1] == "send") {
+
+ if (path.size() == 3 && rest.size() == 2) {
+ if (path[2] == "gain") {
+ _subtype = SendGain;
+ _target.push_back (atoi (rest[1]));
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+uint32_t
+ControllableDescriptor::rid() const
+{
+ if (banked()) {
+ return _rid + _bank_offset;
+ }
+
+ return _rid;
+}
+
+uint32_t
+ControllableDescriptor::target (uint32_t n) const
+{
+ if (n < _target.size()) {
+ return _target[n];
+ }
+
+ return 0;
+}
diff --git a/libs/pbd/pbd/controllable_descriptor.h b/libs/pbd/pbd/controllable_descriptor.h
new file mode 100644
index 0000000000..164cac259d
--- /dev/null
+++ b/libs/pbd/pbd/controllable_descriptor.h
@@ -0,0 +1,83 @@
+/*
+ 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 __pbd_controllable_descriptor_h__
+#define __pbd_controllable_descriptor_h__
+
+#include <vector>
+#include <string>
+#include <stdint.h>
+
+namespace PBD {
+
+class ControllableDescriptor {
+public:
+ enum TopLevelType {
+ RemoteControlID,
+ NamedRoute
+ };
+
+ enum SubType {
+ Gain,
+ Solo,
+ Mute,
+ Recenable,
+ Pan,
+ Balance,
+ SendGain,
+ PluginParameter
+ };
+
+ ControllableDescriptor ()
+ : _top_level_type (RemoteControlID)
+ , _subtype (Gain)
+ , _rid (0)
+ , _banked (false)
+ , _bank_offset (0)
+ {}
+
+ int set (const std::string&);
+
+ /* it is only valid to call top_level_name() if top_level_type() returns
+ NamedRoute
+ */
+
+ TopLevelType top_level_type() const { return _top_level_type; }
+ const std::string& top_level_name() const { return _top_level_name; }
+
+ SubType subtype() const { return _subtype; }
+
+ uint32_t rid() const;
+ uint32_t target (uint32_t n) const;
+ bool banked() const { return _banked; }
+
+ void set_bank_offset (uint32_t o) { _bank_offset = o; }
+
+private:
+ TopLevelType _top_level_type;
+ SubType _subtype;
+ std::string _top_level_name;
+ uint32_t _rid;
+ std::vector<uint32_t> _target;
+ uint32_t _banked;
+ uint32_t _bank_offset;
+};
+
+}
+
+#endif /* __pbd_controllable_descriptor_h__ */
diff --git a/libs/pbd/wscript b/libs/pbd/wscript
index 3794a37e81..1f458678bd 100644
--- a/libs/pbd/wscript
+++ b/libs/pbd/wscript
@@ -57,6 +57,7 @@ def build(bld):
command.cc
convert.cc
controllable.cc
+ controllable_descriptor.cc
crossthread.cc
enumwriter.cc
event_loop.cc
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index 42c5358816..f092fabb59 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -23,6 +23,7 @@
#include <sstream>
#include <algorithm>
+#include "pbd/controllable_descriptor.h"
#include "pbd/error.h"
#include "pbd/failed_constructor.h"
#include "pbd/pathscanner.h"
@@ -711,11 +712,13 @@ GenericMidiControlProtocol::reset_controllables ()
MIDIControllable* existingBinding = (*iter);
if (!existingBinding->learned()) {
- uint32_t rid = existingBinding->rid();
- if (existingBinding->bank_relative()) {
- rid += _current_bank * _bank_size;
+ ControllableDescriptor& desc (existingBinding->descriptor());
+
+ if (desc.banked()) {
+ desc.set_bank_offset (_current_bank * _bank_size);
}
- boost::shared_ptr<Controllable> c = session->controllable_by_rid_and_name (rid, existingBinding->what().c_str());
+
+ boost::shared_ptr<Controllable> c = session->controllable_by_descriptor (desc);
existingBinding->set_controllable (c.get());
}
}
diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc
index 2942a94ad2..d960140958 100644
--- a/libs/surfaces/generic_midi/midicontrollable.cc
+++ b/libs/surfaces/generic_midi/midicontrollable.cc
@@ -24,6 +24,7 @@
#include <climits>
#include "pbd/error.h"
+#include "pbd/controllable_descriptor.h"
#include "pbd/xml++.h"
#include "midi++/port.h"
@@ -41,6 +42,7 @@ using namespace ARDOUR;
MIDIControllable::MIDIControllable (Port& p, bool is_bistate)
: controllable (0)
+ , _descriptor (0)
, _port (p)
, bistate (is_bistate)
{
@@ -55,8 +57,10 @@ MIDIControllable::MIDIControllable (Port& p, bool is_bistate)
MIDIControllable::MIDIControllable (Port& p, Controllable& c, bool is_bistate)
: controllable (&c)
+ , _descriptor (0)
, _port (p)
, bistate (is_bistate)
+
{
_learned = true; /* from controllable */
setting = false;
@@ -76,48 +80,9 @@ int
MIDIControllable::init (const std::string& s)
{
_current_uri = s;
-
- if (!_current_uri.empty()) {
-
- /* parse URI to get remote control ID and "what" is to be controlled */
-
- string::size_type last_slash;
- string useful_part;
-
- if ((last_slash = _current_uri.find_last_of ('/')) == string::npos) {
- return -1;
- }
-
- useful_part = _current_uri.substr (last_slash+1);
-
- char ridstr[64];
- char what[64];
-
- if (sscanf (useful_part.c_str(), "rid=%63[^?]?%63s", ridstr, what) != 2) {
- return -1;
- }
-
- _what = what;
-
- /* now parse RID string and determine if its a bank-driven ID */
-
- if (strncmp (ridstr, "B-", 2) == 0) {
-
- if (sscanf (&ridstr[2], "%" PRIu32, &_rid) != 1) {
- return -1;
- }
-
- _bank_relative = true;
-
- } else {
- if (sscanf (&ridstr[2], "%" PRIu32, &_rid) != 1) {
- return -1;
- }
- _bank_relative = false;
- }
- }
-
- return 0;
+ delete _descriptor;
+ _descriptor = new ControllableDescriptor;
+ return _descriptor->set (s);
}
void
diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h
index a635eaea10..0ce28ecabd 100644
--- a/libs/surfaces/generic_midi/midicontrollable.h
+++ b/libs/surfaces/generic_midi/midicontrollable.h
@@ -30,12 +30,14 @@
#include "ardour/types.h"
-namespace MIDI {
-
-class Channel;
-class Port;
-class Parser;
+namespace PBD {
+ class ControllableDescriptor;
+}
+namespace MIDI {
+ class Channel;
+ class Port;
+ class Parser;
}
class MIDIControllable : public PBD::Stateful
@@ -74,6 +76,8 @@ class MIDIControllable : public PBD::Stateful
void set_controllable (PBD::Controllable*);
const std::string& current_uri() const { return _current_uri; }
+ PBD::ControllableDescriptor& descriptor() const { return *_descriptor; }
+
std::string control_description() const { return _control_description; }
XMLNode& get_state (void);
@@ -86,6 +90,7 @@ class MIDIControllable : public PBD::Stateful
private:
PBD::Controllable* controllable;
+ PBD::ControllableDescriptor* _descriptor;
std::string _current_uri;
MIDI::Port& _port;
bool setting;