summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour/port_set.h
blob: 51673472c399ab86f3402ce0ba1de86843bebaf0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
    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.
*/

#ifndef __ardour_port_set_h__
#define __ardour_port_set_h__

#include <vector>
#include <ardour/port.h>
#include <ardour/audio_port.h>
#include <ardour/midi_port.h>
#include <ardour/chan_count.h>

namespace ARDOUR {


/** An ordered list of Ports, possibly of various types.
 *
 * This allows access to all the ports as a list, ignoring type, or accessing
 * the nth port of a given type.  Note that port(n) and nth_audio_port(n) may
 * NOT return the same port.
 */
class PortSet {
public:
	PortSet();

	size_t num_ports() const;
	size_t num_ports(DataType type) const { return _ports[type].size(); }

	void add(Port* port);
	bool remove(Port* port);

	/** nth port */
	Port* port(size_t index) const;
	
	/** nth port of type @a t, or nth port if t = NIL */
	Port* port(DataType t, size_t index) const;

	AudioPort* nth_audio_port(size_t n) const;
	
	MidiPort* nth_midi_port(size_t n) const;

	bool contains(const Port* port) const;
	
	/** Remove all ports from the PortSet.  Ports are not deregistered with
	 * the engine, it's the caller's responsibility to not leak here!
	 */
	void clear() { _ports.clear(); }

	const ChanCount& count() const { return _count; }

	bool empty() const { return (_count.n_total() == 0); }

	// ITERATORS
	
	// FIXME: this is a filthy copy-and-paste mess
	
	class iterator {
	public:

		Port& operator*()  { return *_set.port(_type, _index); }
		Port* operator->() { return _set.port(_type, _index); }
		iterator& operator++() { ++_index; return *this; } // yes, prefix only
		bool operator==(const iterator& other) { return (_index == other._index); }
		bool operator!=(const iterator& other) { return (_index != other._index); }

	private:
		friend class PortSet;

		iterator(PortSet& list, DataType type, size_t index)
			: _set(list), _type(type), _index(index) {}

		PortSet& _set;
		DataType _type; ///< Ignored if NIL (to iterator over entire set)
		size_t   _index;
	};

	iterator begin(DataType type = DataType::NIL)
		{ return iterator(*this, type, 0); }
	
	iterator end(DataType type = DataType::NIL)
	{
		return iterator(*this, type,
			(type == DataType::NIL) ? _count.n_total() : _count.get(type));
	}
	
	// FIXME: typeify
	class const_iterator {
	public:

		const Port& operator*()  { return *_set.port(_index); }
		const Port* operator->() { return _set.port(_index); }
		const_iterator& operator++() { ++_index; return *this; } // yes, prefix only
		bool operator==(const const_iterator& other) { return (_index == other._index); }
		bool operator!=(const const_iterator& other) { return (_index != other._index); }

	private:
		friend class PortSet;

		const_iterator(const PortSet& list, size_t index) : _set(list), _index(index) {}

		const PortSet& _set;
		size_t          _index;
	};

	const_iterator begin() const { return const_iterator(*this, 0); }
	const_iterator end()   const { return const_iterator(*this, _count.n_total()); }


	class audio_iterator {
	public:

		AudioPort& operator*()  { return *_set.nth_audio_port(_index); }
		AudioPort* operator->()  { return _set.nth_audio_port(_index); }
		audio_iterator& operator++() { ++_index; return *this; } // yes, prefix only
		bool operator==(const audio_iterator& other) { return (_index == other._index); }
		bool operator!=(const audio_iterator& other) { return (_index != other._index); }

	private:
		friend class PortSet;

		audio_iterator(PortSet& list, size_t index) : _set(list), _index(index) {}

		PortSet& _set;
		size_t    _index;
	};

	audio_iterator audio_begin() { return audio_iterator(*this, 0); }
	audio_iterator audio_end()   { return audio_iterator(*this, _count.n_audio()); }

private:	
	// Prevent copies (undefined)
	PortSet(const PortSet& copy);
	void operator=(const PortSet& other);

	typedef std::vector<Port*> PortVec;
	
	// Vector of vectors, indexed by DataType::to_index()
	std::vector<PortVec> _ports;

	ChanCount _count;
};


} // namespace ARDOUR

#endif // __ardour_port_set_h__