X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fport_set.cc;h=6096e356f5d69faf326977a3697a0ea54fe3ca23;hb=d89f209f4a8e94c06de2895ff6fd1830c0e5419d;hp=22fb032c09b2f36a279cbeffe7e95658cbc827f5;hpb=30c08ba655330232767554c48bda1975bfb5628c;p=ardour.git diff --git a/libs/ardour/port_set.cc b/libs/ardour/port_set.cc index 22fb032c09..6096e356f5 100644 --- a/libs/ardour/port_set.cc +++ b/libs/ardour/port_set.cc @@ -1,22 +1,29 @@ /* - Copyright (C) 2006 Paul Davis - + Copyright (C) 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. */ -#include +#include + +#include "ardour/audio_port.h" +#include "ardour/midi_port.h" +#include "ardour/port.h" +#include "ardour/port_set.h" + +using std::string; namespace ARDOUR { @@ -26,86 +33,140 @@ PortSet::PortSet() _ports.push_back( PortVec() ); } -static bool sort_ports_by_name (Port* a, Port* b) +static bool sort_ports_by_name (boost::shared_ptr a, boost::shared_ptr b) +{ + string aname (a->name()); + string bname (b->name()); + + string::size_type last_digit_position_a = aname.size(); + string::reverse_iterator r_iterator = aname.rbegin(); + + while (r_iterator!= aname.rend() && Glib::Unicode::isdigit(*r_iterator)) { + r_iterator++; + last_digit_position_a--; + } + + string::size_type last_digit_position_b = bname.size(); + r_iterator = bname.rbegin(); + + while (r_iterator != bname.rend() && Glib::Unicode::isdigit(*r_iterator)) { + r_iterator++; + last_digit_position_b--; + } + + // if some of the names don't have a number as posfix, compare as strings + + if (last_digit_position_a == aname.size() or last_digit_position_b == bname.size()) { + return aname < bname; + } + + const std::string prefix_a = aname.substr(0, last_digit_position_a - 1); + const unsigned int posfix_a = std::atoi(aname.substr(last_digit_position_a, aname.size() - last_digit_position_a).c_str()); + const std::string prefix_b = bname.substr(0, last_digit_position_b - 1); + const unsigned int posfix_b = std::atoi(bname.substr(last_digit_position_b, bname.size() - last_digit_position_b).c_str()); + + if (prefix_a != prefix_b) { + return aname < bname; + } else { + return posfix_a < posfix_b; + } +} + + +static bool sort_ports_by_type_and_name (boost::shared_ptr a, boost::shared_ptr b) { - return (a->name() < b->name()); + if (a->type() != b->type()) { + return a->type() < b->type(); + } + + return sort_ports_by_name (a, b); } void -PortSet::add_port(Port* port) +PortSet::add (boost::shared_ptr port) { - const size_t list_index = port->type().to_index(); - assert(list_index < _ports.size()); - - PortVec& v = _ports[list_index]; - + PortVec& v = _ports[port->type()]; + v.push_back(port); + _all_ports.push_back(port); + sort(v.begin(), v.end(), sort_ports_by_name); + sort(_all_ports.begin(), _all_ports.end(), sort_ports_by_type_and_name); + + _count.set(port->type(), _count.get(port->type()) + 1); + assert(_count.get(port->type()) == _ports[port->type()].size()); +} - _chan_count.set_count(port->type(), _chan_count.get_count(port->type()) + 1); +bool +PortSet::remove (boost::shared_ptr port) +{ + PortVec::iterator i = find(_all_ports.begin(), _all_ports.end(), port); + if (i != _all_ports.end()) { + _all_ports.erase(i); + } + + for (std::vector::iterator l = _ports.begin(); l != _ports.end(); ++l) { + PortVec::iterator i = find(l->begin(), l->end(), port); + if (i != l->end()) { + l->erase(i); + _count.set(port->type(), _count.get(port->type()) - 1); + return true; + } + } - assert(_chan_count.get_count(port->type()) == _ports[port->type().to_index()].size()); + return false; } - /** Get the total number of ports (of all types) in the PortSet */ size_t PortSet::num_ports() const { - size_t ret = 0; - - for (std::vector::const_iterator l = _ports.begin(); l != _ports.end(); ++l) - ret += (*l).size(); - - return ret; + return _all_ports.size(); } bool -PortSet::contains(const Port* port) const +PortSet::contains (boost::shared_ptr port) const { - for (std::vector::const_iterator l = _ports.begin(); l != _ports.end(); ++l) - if (find((*l).begin(), (*l).end(), port) != (*l).end()) - return true; - - return false; + return find(_all_ports.begin(), _all_ports.end(), port) != _all_ports.end(); } -Port* +boost::shared_ptr PortSet::port(size_t n) const { - // This is awesome - - size_t size_so_far = 0; - - for (std::vector::const_iterator l = _ports.begin(); l != _ports.end(); ++l) { - if (n < size_so_far + (*l).size()) - return (*l)[n - size_so_far]; - else - size_so_far += (*l).size(); - } - - return NULL; // n out of range + assert(n < _all_ports.size()); + return _all_ports[n]; } -Port* -PortSet::nth_port_of_type(DataType type, size_t n) const +boost::shared_ptr +PortSet::port(DataType type, size_t n) const { - const PortVec& v = _ports[type.to_index()]; - assert(n < v.size()); - return v[n]; + if (type == DataType::NIL) { + return port(n); + } else { + const PortVec& v = _ports[type]; + assert(n < v.size()); + return v[n]; + } } -AudioPort* +boost::shared_ptr PortSet::nth_audio_port(size_t n) const { - return dynamic_cast(nth_port_of_type(DataType::AUDIO, n)); + return boost::dynamic_pointer_cast (port (DataType::AUDIO, n)); } -MidiPort* +boost::shared_ptr PortSet::nth_midi_port(size_t n) const { - return dynamic_cast(nth_port_of_type(DataType::MIDI, n)); + return boost::dynamic_pointer_cast (port (DataType::MIDI, n)); +} + +void +PortSet::clear() +{ + _ports.clear(); + _all_ports.clear(); } } // namepace ARDOUR