* Add SysEx Support to MidiModel / SMF
[ardour.git] / libs / ardour / port.cc
1 /*
2     Copyright (C) 2009 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 #include "ardour/audioengine.h"
22 #include "ardour/i18n.h"
23 #include "pbd/failed_constructor.h"
24 #include "pbd/error.h"
25 #include "pbd/compose.h"
26 #include <stdexcept>
27
28 using namespace std;
29 using namespace ARDOUR;
30
31 AudioEngine* Port::_engine = 0;
32
33 /** @param n Port short name */
34 Port::Port (std::string const & n, DataType t, Flags f, bool e) 
35         : _jack_port (0)
36         , _last_monitor (false)
37         , _latency (0)
38         , _name (n)
39         , _flags (f)
40 {
41
42         /* Unfortunately we have to pass the DataType into this constructor so that we can
43            create the right kind of JACK port; aside from this we'll use the virtual function type ()
44            to establish type. 
45         */
46
47         assert (_name.find_first_of (':') == std::string::npos);
48         
49         if (e) {
50                 try {
51                         cerr << "NEW PORT " << _name << " ext = " << e << endl;
52                         do_make_external (t);
53                 }
54                 catch (...) {
55                         throw failed_constructor ();
56                 }
57         }
58 }
59
60 /** Port destructor */
61 Port::~Port ()
62 {
63         if (_jack_port) {
64                 jack_port_unregister (_engine->jack (), _jack_port);
65         }
66 }
67
68 /** Make this port externally visible by setting it up to use a JACK port.
69  * @param t Data type, so that we can call this method from the constructor.
70  */
71 void
72 Port::do_make_external (DataType t)
73 {
74         if (_jack_port) {
75                 /* already external */
76                 return;
77         }
78         
79         if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) {
80                 throw std::runtime_error ("Could not register JACK port");
81         }
82 }
83
84 void
85 Port::make_external ()
86 {
87         do_make_external (type ());
88 }
89
90 /** @return true if this port is connected to anything */
91 bool
92 Port::connected () const
93 {
94         if (!_connections.empty ()) {
95                 /* connected to a Port* */
96                 return true;
97         }
98
99         if (_jack_port == 0) {
100                 /* not using a JACK port, so can't be connected to anything else */
101                 return false;
102         }
103         
104         return (jack_port_connected (_jack_port) != 0);
105 }
106
107 /** @return true if this port is connected to anything via an external port */
108 bool
109 Port::externally_connected () const
110 {
111         if (_jack_port == 0) {
112                 /* not using a JACK port, so can't be connected to anything else */
113                 return false;
114         }
115         
116         return (jack_port_connected (_jack_port) != 0);
117 }
118
119 int
120 Port::disconnect_all ()
121 {
122         /* Disconnect from Port* connections */
123         for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
124                 (*i)->_connections.erase (this);
125         }
126
127         _connections.clear ();
128
129         /* And JACK connections */
130         jack_port_disconnect (_engine->jack(), _jack_port);
131         _named_connections.clear ();
132
133         check_buffer_status ();
134
135         return 0;
136 }
137
138 /** @param o Port name
139  * @return true if this port is connected to o, otherwise false.
140  */
141 bool
142 Port::connected_to (std::string const & o) const
143 {
144         std::string const full = _engine->make_port_name_non_relative (o);
145         std::string const shrt = _engine->make_port_name_non_relative (o);
146         
147         if (_jack_port && jack_port_connected_to (_jack_port, full.c_str ())) {
148                 /* connected via JACK */
149                 return true;
150         }
151
152         for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
153                 if ((*i)->name () == shrt) {
154                         /* connected internally */
155                         return true;
156                 }
157         }
158
159         return false;
160 }
161
162 /** @param o Filled in with port full names of ports that we are connected to */
163 int
164 Port::get_connections (std::vector<std::string> & c) const
165 {
166         int n = 0;
167
168         /* JACK connections */
169         if (_jack_port) {
170                 const char** jc = jack_port_get_connections (_jack_port);
171                 if (jc) {
172                         for (int i = 0; jc[i]; ++i) {
173                                 c.push_back (jc[i]);
174                                 ++n;
175                         }
176                 }
177         }
178
179         /* Internal connections */
180         for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
181                 std::string const full = _engine->make_port_name_non_relative ((*i)->name());
182                 c.push_back (full);
183                 ++n;
184         }
185
186         return n;
187 }
188
189 int
190 Port::connect (std::string const & other)
191 {
192         /* caller must hold process lock */
193
194         std::string const other_shrt = _engine->make_port_name_non_relative (other);
195         
196         Port* p = _engine->get_port_by_name_locked (other_shrt);
197         
198         int r;
199         
200         if (p && !p->external ()) {
201                 /* non-external Ardour port; connect using Port* */
202                 r = connect (p);
203         } else {
204                 /* connect using name */
205
206                 /* for this to work, we must be an external port */
207                 if (!external ()) {
208                         make_external ();
209                 }
210
211                 std::string const this_shrt = _engine->make_port_name_non_relative (_name);
212
213                 if (sends_output ()) {
214                         r = jack_connect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
215                 } else {
216                         r = jack_connect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str());
217                 }
218
219                 if (r == 0) {
220                         _named_connections.insert (other);
221                 }
222         }
223
224         check_buffer_status ();
225
226         return r;
227 }
228
229 int
230 Port::disconnect (std::string const & other)
231 {
232         /* caller must hold process lock */
233
234         std::string const other_shrt = _engine->make_port_name_non_relative (other);
235         
236         Port* p = _engine->get_port_by_name_locked (other_shrt);
237         int r;
238
239         if (p && !p->external ()) {
240                 /* non-external Ardour port; disconnect using Port* */
241                 r = disconnect (p);
242         } else {
243                 /* disconnect using name */
244
245                 std::string const this_shrt = _engine->make_port_name_non_relative (_name);
246
247                 if (sends_output ()) {
248                         r = jack_disconnect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
249                 } else {
250                         r = jack_disconnect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str ());
251                 }
252
253                 if (r == 0) {
254                         _named_connections.erase (other);
255                 }
256
257                 check_buffer_status ();
258         }
259
260         return r;
261 }
262
263
264 bool
265 Port::connected_to (Port* o) const
266 {
267         return connected_to (o->name ());
268 }
269
270 int
271 Port::connect (Port* o)
272 {
273         /* caller must hold process lock */
274
275         if (external () && o->external ()) {
276                 /* we're both external; connect using name */
277                 return connect (o->name ());
278         }
279
280         /* otherwise connect by Port* */
281         _connections.insert (o);
282         o->_connections.insert (this);
283
284         check_buffer_status ();
285         o->check_buffer_status ();
286
287         return 0;
288 }
289
290 int
291 Port::disconnect (Port* o)
292 {
293         if (external () && o->external ()) {
294                 /* we're both external; try disconnecting using name */
295                 int const r = disconnect (o->name ());
296                 if (r == 0) {
297                         return 0;
298                 }
299         }
300         
301         _connections.erase (o);
302         o->_connections.erase (this);
303
304         check_buffer_status ();
305         o->check_buffer_status ();
306
307         return 0;
308 }
309
310 void
311 Port::set_engine (AudioEngine* e)
312 {
313         _engine = e;
314 }
315
316 void
317 Port::ensure_monitor_input (bool yn)
318 {
319         if (_jack_port) {
320                 jack_port_ensure_monitor (_jack_port, yn);
321         }
322 }
323
324 bool
325 Port::monitoring_input () const
326 {
327         if (_jack_port) {
328                 return jack_port_monitoring_input (_jack_port);
329         } else {
330                 return false;
331         }
332 }
333
334 void
335 Port::reset ()
336 {
337         _last_monitor = false;
338
339         // XXX
340         // _metering = 0;
341         // reset_meters ();
342 }
343
344 void
345 Port::recompute_total_latency () const
346 {
347 #ifdef HAVE_JACK_RECOMPUTE_LATENCY      
348         if (_jack_port) {
349                 jack_recompute_total_latency (_engine->jack (), _jack_port);
350         }
351 #endif  
352 }
353
354 nframes_t
355 Port::total_latency () const
356 {
357         if (_jack_port) {
358                 return jack_port_get_total_latency (_engine->jack (), _jack_port);
359         } else {
360                 return _latency;
361         }
362 }
363
364 int
365 Port::reestablish ()
366 {
367         if (!_jack_port) {
368                 return 0;
369         }
370
371         _jack_port = jack_port_register (_engine->jack(), _name.c_str(), type().to_jack_type(), _flags, 0);
372
373         if (_jack_port == 0) {
374                 PBD::error << string_compose (_("could not reregister %1"), _name) << endmsg;
375                 return -1;
376         }
377
378         reset ();
379
380         return 0;
381 }
382
383
384 int
385 Port::reconnect ()
386 {
387         /* caller must hold process lock; intended to be used only after reestablish() */
388
389         if (!_jack_port) {
390                 return 0;
391         }
392         
393         for (std::set<string>::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) {
394                 if (connect (*i)) {
395                         return -1;
396                 }
397         }
398
399         return 0;
400 }
401
402 /** @param n Short name */
403 int
404 Port::set_name (std::string const & n)
405 {
406         assert (_name.find_first_of (':') == std::string::npos);
407
408         int r = 0;
409         
410         if (_jack_port) {
411                 r = jack_port_set_name (_jack_port, n.c_str());
412                 if (r == 0) {
413                         _name = n;
414                 }
415         } else {
416                 _name = n;
417         }
418
419         return r;
420 }
421
422 void
423 Port::set_latency (nframes_t n)
424 {
425         _latency = n;
426 }
427
428 void
429 Port::request_monitor_input (bool yn)
430 {
431         if (_jack_port) {
432                 jack_port_request_monitor (_jack_port, yn);
433         }
434 }
435
436 void
437 Port::check_buffer_status ()
438 {
439         if (external() && receives_input()) {
440                 if (!externally_connected()) {
441                         if (!_connections.empty()) {
442
443                                 /* There are no external connections, so the
444                                    external port buffer will be the silent buffer. We cannot write into it.
445                                    But we have to write somewhere because there is at least one internal
446                                    connection that is supplying us with data.
447                                 */
448
449                                 if (!using_internal_data()) {
450                                         use_internal_data ();
451                                 }
452
453                         } else {
454                                 
455                                 /* There are no external connections and no internal ones
456                                    either, so we can revert to use the externally supplied
457                                    buffer which will be silent (whatever the semantics of 
458                                    that are for a particular data type.
459                                 */
460
461                                 if (using_internal_data()) {
462                                         use_external_data ();
463                                 }
464                         }
465                 } 
466         }
467 }