Apply MIDI looping patch from torbenh, with minor changes.
[ardour.git] / libs / ardour / port.cc
1 /*
2     Copyright (C) 2002-2006 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <ardour/port.h>
21
22 using namespace ARDOUR;
23 using namespace std;
24
25 AudioEngine* Port::engine = 0;
26
27 Port::Port (const std::string& name, Flags flgs)
28         : _flags (flgs)
29         , _name (name)
30         , _metering (0)
31         , _last_monitor (false)
32 {
33 }
34
35 Port::~Port ()
36 {
37         disconnect_all ();
38 }
39
40 void
41 Port::reset ()
42 {
43         _last_monitor = false;
44 }
45
46 void
47 Port::set_engine (AudioEngine* e) 
48 {
49         engine = e;
50 }
51
52 int
53 Port::connect (Port& other)
54 {
55         /* caller must hold process lock */
56
57         pair<set<Port*>::iterator,bool> result;
58
59         result = _connections.insert (&other);
60
61         if (result.second) {
62                 return 0;
63         } else {
64                 return 1;
65         }
66 }
67
68 int
69 Port::disconnect (Port& other)
70 {
71         /* caller must hold process lock */
72         
73         for (set<Port*>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
74                 if ((*i) == &other) {
75                         _connections.erase (i);
76                         return 0;
77                 }
78         }
79
80         return -1;
81 }
82
83
84 int
85 Port::disconnect_all ()
86 {
87         /* caller must hold process lock */
88
89         _connections.clear ();
90         return 0;
91 }
92
93 void
94 Port::set_latency (nframes_t val)
95 {
96         _latency = val;
97 }
98
99 bool
100 Port::connected() const
101 {
102         /* caller must hold process lock */
103         return !_connections.empty();
104 }
105
106 bool
107 Port::connected_to (const string& portname) const
108 {
109         /* caller must hold process lock */
110
111         for (set<Port*>::const_iterator p = _connections.begin(); p != _connections.end(); ++p) {
112                 if ((*p)->name() == portname) {
113                         return true;
114                 }
115         }
116
117         return false;
118 }
119
120 int
121 Port::get_connections (vector<string>& names) const
122 {
123         /* caller must hold process lock */
124         int i = 0;
125         set<Port*>::const_iterator p;
126
127         for (i = 0, p = _connections.begin(); p != _connections.end(); ++p, ++i) {
128                 names.push_back ((*p)->name());
129         }
130
131         return i;
132 }
133
134
135 //-------------------------------------
136
137 int
138 PortFacade::set_name (const std::string& str)
139 {
140         int ret;
141
142         if (_ext_port) {
143                 if ((ret = _ext_port->set_name (str)) == 0) {
144                         _name = _ext_port->name();
145                 }
146         } else {
147                 _name = str;
148                 ret = 0;
149         }
150
151         return ret;
152 }
153
154 string
155 PortFacade::short_name ()  const
156 {
157         if (_ext_port) {
158                 return _ext_port->short_name(); 
159         } else {
160                 return _name;
161         }
162 }
163
164
165 int
166 PortFacade::reestablish ()
167 {
168         if (_ext_port) {
169                 return _ext_port->reestablish ();
170         } else {
171                 return 0;
172         }
173 }
174
175
176 int
177 PortFacade::reconnect()
178 {
179         if (_ext_port) {
180                 return _ext_port->reconnect ();
181         } else {
182                 return 0;
183         }
184 }
185
186 void
187 PortFacade::set_latency (nframes_t val)
188 {
189         if (_ext_port) {
190                 _ext_port->set_latency (val);
191         } else {
192                 _latency = val;
193         }
194 }
195
196 nframes_t
197 PortFacade::latency() const
198 {
199         if (_ext_port) {
200                 return _ext_port->latency();
201         } else {
202                 return _latency;
203         }
204 }
205
206 nframes_t
207 PortFacade::total_latency() const
208 {
209         if (_ext_port) {
210                 return _ext_port->total_latency();
211         } else {
212                 return _latency;
213         }
214 }
215
216 bool
217 PortFacade::monitoring_input() const
218 {
219         if (_ext_port) {
220                 return _ext_port->monitoring_input ();
221         } else {
222                 return false;
223         }
224 }
225
226 void
227 PortFacade::ensure_monitor_input (bool yn)
228 {
229         if (_ext_port) {
230                 _ext_port->ensure_monitor_input (yn);
231         }
232 }
233
234 void
235 PortFacade::request_monitor_input (bool yn)
236 {
237         if (_ext_port) {
238                 _ext_port->request_monitor_input (yn);
239         } 
240 }
241
242 int
243 PortFacade::connect (Port& other)
244 {
245         int ret;
246         
247         if (_ext_port) {
248                 ret = _ext_port->connect (other);
249         } else {
250                 ret = 0;
251         }
252
253         if (ret == 0) {
254                 ret = Port::connect (other);
255         }
256
257         return ret;
258 }
259
260 int
261 PortFacade::connect (const std::string& other)
262 {
263         PortConnectableByName* pcn;
264
265         if (!_ext_port) {
266                 return -1;
267         }
268                 
269         pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
270
271         if (pcn) {
272                 return pcn->connect (other);
273         } else {
274                 return -1;
275         }
276 }
277
278
279 int
280 PortFacade::disconnect (Port& other)
281 {
282         int reta;
283         int retb;
284         
285         if (_ext_port) {
286                 reta = _ext_port->disconnect (other);
287         } else {
288                 reta = 0;
289         }
290
291         retb = Port::disconnect (other);
292
293         return reta || retb;
294 }
295
296 int 
297 PortFacade::disconnect_all ()
298 {
299         int reta = 0;
300         int retb = 0;
301
302         if (_ext_port) {
303                 reta = _ext_port->disconnect_all ();
304         } 
305
306         retb = Port::disconnect_all ();
307
308         return reta || retb;
309 }
310                 
311 int
312 PortFacade::disconnect (const std::string& other)
313 {
314         PortConnectableByName* pcn;
315
316         if (!_ext_port) {
317                 return -1;
318         }
319                 
320         pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
321
322         if (pcn) {
323                 return pcn->disconnect (other);
324         } else {
325                 return -1;
326         }
327 }
328
329 bool
330 PortFacade::connected () const 
331 {
332         if (Port::connected()) {
333                 return true;
334         }
335
336         if (_ext_port) {
337                 return _ext_port->connected();
338         }
339
340         return false;
341 }
342 bool
343 PortFacade::connected_to (const std::string& portname) const 
344 {
345         if (Port::connected_to (portname)) {
346                 return true;
347         }
348
349         if (_ext_port) {
350                 return _ext_port->connected_to (portname);
351         }
352
353         return false;
354
355 }
356
357 int
358 PortFacade::get_connections (vector<string>& names) const 
359 {
360         int i = 0;
361
362         if (_ext_port) {
363                 i = _ext_port->get_connections (names);
364         }
365
366         i += Port::get_connections (names);
367
368         return i;
369 }
370
371 void
372 PortFacade::reset ()
373 {
374         Port::reset ();
375
376         if (_ext_port) {
377                 _ext_port->reset ();
378         }
379 }