Reduce overhead of multi-type-ness (last Summer's SoC):
[ardour.git] / libs / ardour / port_set.cc
1 /*
2     Copyright (C) 2006 Paul Davis 
3     
4     This program is free software; you can redistribute it and/or modify it
5     under the terms of the GNU General Public License as published by the Free
6     Software Foundation; either version 2 of the License, or (at your option)
7     any later version.
8     
9     This program is distributed in the hope that it will be useful, but WITHOUT
10     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12     for more details.
13     
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <ardour/port_set.h>
20
21 namespace ARDOUR {
22
23 PortSet::PortSet()
24 {
25         for (size_t i=0; i < DataType::num_types; ++i)
26                 _ports.push_back( PortVec() );
27 }
28
29 static bool sort_ports_by_name (Port* a, Port* b)
30 {
31         return (a->name() < b->name());
32 }
33
34 void
35 PortSet::add(Port* port)
36 {
37         PortVec& v = _ports[port->type()];
38         
39         v.push_back(port);
40         sort(v.begin(), v.end(), sort_ports_by_name);
41
42         _count.set(port->type(), _count.get(port->type()) + 1);
43
44         assert(_count.get(port->type()) == _ports[port->type()].size());
45 }
46
47 bool
48 PortSet::remove(Port* port)
49 {
50         for (std::vector<PortVec>::iterator l = _ports.begin(); l != _ports.end(); ++l) {
51                 PortVec::iterator i = find(l->begin(), l->end(), port);
52                 if (i != l->end()) {
53                         l->erase(i);
54                         _count.set(port->type(), _count.get(port->type()) - 1);
55                         return true;
56                 }
57         }
58
59         return false;
60 }
61
62 /** Get the total number of ports (of all types) in the PortSet
63  */
64 size_t
65 PortSet::num_ports() const
66 {
67         size_t ret = 0;
68
69         for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l)
70                 ret += (*l).size();
71
72         return ret;
73 }
74
75 bool
76 PortSet::contains(const Port* port) const
77 {
78         for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l)
79                 if (find((*l).begin(), (*l).end(), port) != (*l).end())
80                         return true;
81
82         return false;
83 }
84
85 Port*
86 PortSet::port(size_t n) const
87 {
88         // This is awesome.  Awesomely slow.
89         
90         size_t size_so_far = 0;
91
92         for (std::vector<PortVec>::const_iterator l = _ports.begin(); l != _ports.end(); ++l) {
93                 if (n < size_so_far + (*l).size())
94                         return (*l)[n - size_so_far];
95                 else
96                         size_so_far += (*l).size();
97         }
98
99         return NULL; // n out of range
100 }
101
102 Port*
103 PortSet::port(DataType type, size_t n) const
104 {
105         if (type == DataType::NIL) {
106                 return port(n);
107         } else {
108                 const PortVec& v = _ports[type];
109                 assert(n < v.size());
110                 return v[n];
111         }
112 }
113
114 AudioPort*
115 PortSet::nth_audio_port(size_t n) const
116 {
117         return dynamic_cast<AudioPort*>(port(DataType::AUDIO, n));
118 }
119
120 MidiPort*
121 PortSet::nth_midi_port(size_t n) const
122 {
123         return dynamic_cast<MidiPort*>(port(DataType::MIDI, n));
124 }
125
126 } // namepace ARDOUR