diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-12-31 23:43:47 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-12-31 23:43:47 +0000 |
commit | 6c717a56e28ebc67bcf041a1ee9887d46700a0e7 (patch) | |
tree | fea823393486d493841d899345cf619ad2f31ca9 /libs | |
parent | e00506b0ad7a40f8e876542e40ac85ab1979adb5 (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.h | 3 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 146 | ||||
-rw-r--r-- | libs/pbd/controllable_descriptor.cc | 150 | ||||
-rw-r--r-- | libs/pbd/pbd/controllable_descriptor.h | 83 | ||||
-rw-r--r-- | libs/pbd/wscript | 1 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.cc | 11 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/midicontrollable.cc | 49 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/midicontrollable.h | 15 |
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, ¶meter_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; |