Ports say when they're going away.
[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         drop_references ();
38         disconnect_all ();
39 }
40
41 void
42 Port::reset ()
43 {
44         _last_monitor = false;
45 }
46
47 void
48 Port::set_engine (AudioEngine* e) 
49 {
50         engine = e;
51 }
52
53 int
54 Port::connect (Port& other)
55 {
56         /* caller must hold process lock */
57
58         pair<set<Port*>::iterator,bool> result;
59
60         result = _connections.insert (&other);
61
62         if (result.second) {
63                 other.GoingAway.connect (sigc::bind (mem_fun (*this, &Port::port_going_away), &other));
64                 return 0;
65         } else {
66                 return 1;
67         }
68 }
69
70 int
71 Port::disconnect (Port& other)
72 {
73         /* caller must hold process lock */
74         
75         for (set<Port*>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
76                 if ((*i) == &other) {
77                         _connections.erase (i);
78                         return 0;
79                 }
80         }
81
82         return -1;
83 }
84
85
86 int
87 Port::disconnect_all ()
88 {
89         /* caller must hold process lock */
90
91         _connections.clear ();
92         return 0;
93 }
94
95 void
96 Port::set_latency (nframes_t val)
97 {
98         _latency = val;
99 }
100
101 bool
102 Port::connected() const
103 {
104         /* caller must hold process lock */
105         return !_connections.empty();
106 }
107
108 bool
109 Port::connected_to (const string& portname) const
110 {
111         /* caller must hold process lock */
112
113         for (set<Port*>::const_iterator p = _connections.begin(); p != _connections.end(); ++p) {
114                 if ((*p)->name() == portname) {
115                         return true;
116                 }
117         }
118
119         return false;
120 }
121
122 int
123 Port::get_connections (vector<string>& names) const
124 {
125         /* caller must hold process lock */
126         int i = 0;
127         set<Port*>::const_iterator p;
128
129         for (i = 0, p = _connections.begin(); p != _connections.end(); ++p, ++i) {
130                 names.push_back ((*p)->name());
131         }
132
133         return i;
134 }
135
136 void
137 Port::port_going_away (Port* p)
138 {
139         /* caller must hold process lock */
140
141         disconnect (*p);
142 }
143
144
145 //-------------------------------------
146
147 int
148 PortFacade::set_name (const std::string& str)
149 {
150         int ret;
151
152         if (_ext_port) {
153                 if ((ret = _ext_port->set_name (str)) == 0) {
154                         _name = _ext_port->name();
155                 }
156         } else {
157                 _name = str;
158                 ret = 0;
159         }
160
161         return ret;
162 }
163
164 string
165 PortFacade::short_name ()  const
166 {
167         if (_ext_port) {
168                 return _ext_port->short_name(); 
169         } else {
170                 return _name;
171         }
172 }
173
174
175 int
176 PortFacade::reestablish ()
177 {
178         if (_ext_port) {
179                 return _ext_port->reestablish ();
180         } else {
181                 return 0;
182         }
183 }
184
185
186 int
187 PortFacade::reconnect()
188 {
189         if (_ext_port) {
190                 return _ext_port->reconnect ();
191         } else {
192                 return 0;
193         }
194 }
195
196 void
197 PortFacade::set_latency (nframes_t val)
198 {
199         if (_ext_port) {
200                 _ext_port->set_latency (val);
201         } else {
202                 _latency = val;
203         }
204 }
205
206 nframes_t
207 PortFacade::latency() const
208 {
209         if (_ext_port) {
210                 return _ext_port->latency();
211         } else {
212                 return _latency;
213         }
214 }
215
216 nframes_t
217 PortFacade::total_latency() const
218 {
219         if (_ext_port) {
220                 return _ext_port->total_latency();
221         } else {
222                 return _latency;
223         }
224 }
225
226 bool
227 PortFacade::monitoring_input() const
228 {
229         if (_ext_port) {
230                 return _ext_port->monitoring_input ();
231         } else {
232                 return false;
233         }
234 }
235
236 void
237 PortFacade::ensure_monitor_input (bool yn)
238 {
239         if (_ext_port) {
240                 _ext_port->ensure_monitor_input (yn);
241         }
242 }
243
244 void
245 PortFacade::request_monitor_input (bool yn)
246 {
247         if (_ext_port) {
248                 _ext_port->request_monitor_input (yn);
249         } 
250 }
251
252 int
253 PortFacade::connect (Port& other)
254 {
255         int ret;
256         
257         if (_ext_port) {
258                 ret = _ext_port->connect (other);
259         } else {
260                 ret = 0;
261         }
262
263         if (ret == 0) {
264                 ret = Port::connect (other);
265         }
266
267         return ret;
268 }
269
270 int
271 PortFacade::connect (const std::string& other)
272 {
273         PortConnectableByName* pcn;
274
275         if (!_ext_port) {
276                 return -1;
277         }
278                 
279         pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
280
281         if (pcn) {
282                 return pcn->connect (other);
283         } else {
284                 return -1;
285         }
286 }
287
288
289 int
290 PortFacade::disconnect (Port& other)
291 {
292         int reta;
293         int retb;
294         
295         if (_ext_port) {
296                 reta = _ext_port->disconnect (other);
297         } else {
298                 reta = 0;
299         }
300
301         retb = Port::disconnect (other);
302
303         return reta || retb;
304 }
305
306 int 
307 PortFacade::disconnect_all ()
308 {
309         int reta = 0;
310         int retb = 0;
311
312         if (_ext_port) {
313                 reta = _ext_port->disconnect_all ();
314         } 
315
316         retb = Port::disconnect_all ();
317
318         return reta || retb;
319 }
320                 
321 int
322 PortFacade::disconnect (const std::string& other)
323 {
324         PortConnectableByName* pcn;
325
326         if (!_ext_port) {
327                 return -1;
328         }
329                 
330         pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
331
332         if (pcn) {
333                 return pcn->disconnect (other);
334         } else {
335                 return -1;
336         }
337 }
338
339 bool
340 PortFacade::connected () const 
341 {
342         if (Port::connected()) {
343                 return true;
344         }
345
346         if (_ext_port) {
347                 return _ext_port->connected();
348         }
349
350         return false;
351 }
352 bool
353 PortFacade::connected_to (const std::string& portname) const 
354 {
355         if (Port::connected_to (portname)) {
356                 return true;
357         }
358
359         if (_ext_port) {
360                 return _ext_port->connected_to (portname);
361         }
362
363         return false;
364
365 }
366
367 int
368 PortFacade::get_connections (vector<string>& names) const 
369 {
370         int i = 0;
371
372         if (_ext_port) {
373                 i = _ext_port->get_connections (names);
374         }
375
376         i += Port::get_connections (names);
377
378         return i;
379 }
380
381 void
382 PortFacade::reset ()
383 {
384         Port::reset ();
385
386         if (_ext_port) {
387                 _ext_port->reset ();
388         }
389 }
390