fix crash when copy'ing latent plugins
[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 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include "pbd/compose.h"
25 #include "pbd/error.h"
26 #include "pbd/failed_constructor.h"
27
28 #include "ardour/audioengine.h"
29 #include "ardour/debug.h"
30 #include "ardour/port.h"
31 #include "ardour/port_engine.h"
32
33 #include "pbd/i18n.h"
34
35 using namespace std;
36 using namespace ARDOUR;
37 using namespace PBD;
38
39 PBD::Signal2<void,boost::shared_ptr<Port>, boost::shared_ptr<Port> > Port::PostDisconnect;
40 PBD::Signal0<void> Port::PortDrop;
41 PBD::Signal0<void> Port::PortSignalDrop;
42
43 bool         Port::_connecting_blocked = false;
44 pframes_t    Port::_global_port_buffer_offset = 0;
45 pframes_t    Port::_cycle_nframes = 0;
46 std::string  Port::state_node_name = X_("Port");
47
48 /* a handy define to shorten what would otherwise be a needlessly verbose
49  * repeated phrase
50  */
51 #define port_engine AudioEngine::instance()->port_engine()
52 #define port_manager AudioEngine::instance()
53
54 /** @param n Port short name */
55 Port::Port (std::string const & n, DataType t, PortFlags f)
56         : _port_buffer_offset (0)
57         , _name (n)
58         , _flags (f)
59         , _last_monitor (false)
60 {
61         _private_playback_latency.min = 0;
62         _private_playback_latency.max = 0;
63         _private_capture_latency.min = 0;
64         _private_capture_latency.max = 0;
65
66         /* Unfortunately we have to pass the DataType into this constructor so that
67            we can create the right kind of port; aside from this we'll use the
68            virtual function type () to establish type.
69         */
70
71         assert (_name.find_first_of (':') == std::string::npos);
72
73         if ((_port_handle = port_engine.register_port (_name, t, _flags)) == 0) {
74                 cerr << "Failed to register port \"" << _name << "\", reason is unknown from here\n";
75                 throw failed_constructor ();
76         }
77
78         PortDrop.connect_same_thread (drop_connection, boost::bind (&Port::drop, this));
79         PortSignalDrop.connect_same_thread (drop_connection, boost::bind (&Port::signal_drop, this));
80         port_manager->PortConnectedOrDisconnected.connect_same_thread (engine_connection,
81                         boost::bind (&Port::port_connected_or_disconnected, this, _1, _3, _5));
82 }
83
84 /** Port destructor */
85 Port::~Port ()
86 {
87         drop ();
88 }
89
90
91 std::string
92 Port::pretty_name(bool fallback_to_name) const
93 {
94         if (_port_handle) {
95                 std::string value;
96                 std::string type;
97                 if (0 == port_engine.get_port_property (_port_handle,
98                                         "http://jackaudio.org/metadata/pretty-name",
99                                         value, type))
100                 {
101                         return value;
102                 }
103         }
104         if (fallback_to_name) {
105                 return name ();
106         }
107         return "";
108 }
109
110 bool
111 Port::set_pretty_name(const std::string& n)
112 {
113         if (_port_handle) {
114                 if (0 == port_engine.set_port_property (_port_handle,
115                                         "http://jackaudio.org/metadata/pretty-name", n, ""))
116                 {
117                         return true;
118                 }
119         }
120         return false;
121 }
122
123 void
124 Port::signal_drop ()
125 {
126         engine_connection.disconnect ();
127 }
128
129 void
130 Port::drop ()
131 {
132         if (_port_handle) {
133                 DEBUG_TRACE (DEBUG::Ports, string_compose ("drop handle for port %1\n", name()));
134                 port_engine.unregister_port (_port_handle);
135                 _port_handle = 0;
136         }
137 }
138
139 void
140 Port::port_connected_or_disconnected (boost::weak_ptr<Port> w0, boost::weak_ptr<Port> w1, bool con)
141 {
142         if (con) {
143                 /* we're only interested in disconnect */
144                 return;
145         }
146         boost::shared_ptr<Port> p0 = w0.lock ();
147         boost::shared_ptr<Port> p1 = w1.lock ();
148         /* a cheaper, less hacky way to do boost::shared_from_this() ...  */
149         boost::shared_ptr<Port> pself = AudioEngine::instance()->get_port_by_name (name());
150
151         if (p0 == pself) {
152                 PostDisconnect (p0, p1); // emit signal
153         }
154         if (p1 == pself) {
155                 PostDisconnect (p1, p0); // emit signal
156         }
157 }
158
159 /** @return true if this port is connected to anything */
160 bool
161 Port::connected () const
162 {
163         if (_port_handle) {
164                 return (port_engine.connected (_port_handle) != 0);
165         }
166         return false;
167 }
168
169 int
170 Port::disconnect_all ()
171 {
172         if (_port_handle) {
173
174                 std::vector<std::string> connections;
175                 get_connections (connections);
176
177                 port_engine.disconnect_all (_port_handle);
178                 _connections.clear ();
179
180                 /* a cheaper, less hacky way to do boost::shared_from_this() ...
181                  */
182                 boost::shared_ptr<Port> pself = port_manager->get_port_by_name (name());
183                 for (vector<string>::const_iterator c = connections.begin(); c != connections.end() && pself; ++c) {
184                         boost::shared_ptr<Port> pother = AudioEngine::instance()->get_port_by_name (*c);
185                         if (pother) {
186                                 PostDisconnect (pself, pother); // emit signal
187                         }
188                 }
189         }
190
191         return 0;
192 }
193
194 /** @param o Port name
195  * @return true if this port is connected to o, otherwise false.
196  */
197 bool
198 Port::connected_to (std::string const & o) const
199 {
200         if (!_port_handle) {
201                 return false;
202         }
203
204         if (!port_engine.available()) {
205                 return false;
206         }
207
208         return port_engine.connected_to (_port_handle, AudioEngine::instance()->make_port_name_non_relative (o));
209 }
210
211 int
212 Port::get_connections (std::vector<std::string> & c) const
213 {
214         if (!port_engine.available()) {
215                 c.insert (c.end(), _connections.begin(), _connections.end());
216                 return c.size();
217         }
218
219         if (_port_handle) {
220                 return port_engine.get_connections (_port_handle, c);
221         }
222
223         return 0;
224 }
225
226 int
227 Port::connect (std::string const & other)
228 {
229         std::string const other_name = AudioEngine::instance()->make_port_name_non_relative (other);
230         std::string const our_name = AudioEngine::instance()->make_port_name_non_relative (_name);
231
232         int r = 0;
233
234         if (_connecting_blocked) {
235                 return r;
236         }
237
238         if (sends_output ()) {
239                 DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2\n", our_name, other_name));
240                 r = port_engine.connect (our_name, other_name);
241         } else {
242                 DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2\n", other_name, our_name));
243                 r = port_engine.connect (other_name, our_name);
244         }
245
246         if (r == 0) {
247                 _connections.insert (other);
248         }
249
250         return r;
251 }
252
253 int
254 Port::disconnect (std::string const & other)
255 {
256         std::string const other_fullname = port_manager->make_port_name_non_relative (other);
257         std::string const this_fullname = port_manager->make_port_name_non_relative (_name);
258
259         int r = 0;
260
261         if (sends_output ()) {
262                 r = port_engine.disconnect (this_fullname, other_fullname);
263         } else {
264                 r = port_engine.disconnect (other_fullname, this_fullname);
265         }
266
267         if (r == 0) {
268                 _connections.erase (other);
269         }
270
271         /* a cheaper, less hacky way to do boost::shared_from_this() ...  */
272         boost::shared_ptr<Port> pself = AudioEngine::instance()->get_port_by_name (name());
273         boost::shared_ptr<Port> pother = AudioEngine::instance()->get_port_by_name (other);
274
275         if (pself && pother) {
276                 /* Disconnecting from another Ardour port: need to allow
277                    a check on whether this may affect anything that we
278                    need to know about.
279                 */
280                 PostDisconnect (pself, pother); // emit signal
281         }
282
283         return r;
284 }
285
286
287 bool
288 Port::connected_to (Port* o) const
289 {
290         return connected_to (o->name ());
291 }
292
293 int
294 Port::connect (Port* o)
295 {
296         return connect (o->name ());
297 }
298
299 int
300 Port::disconnect (Port* o)
301 {
302         return disconnect (o->name ());
303 }
304
305 void
306 Port::request_input_monitoring (bool yn)
307 {
308         if (_port_handle) {
309                 port_engine.request_input_monitoring (_port_handle, yn);
310         }
311 }
312
313 void
314 Port::ensure_input_monitoring (bool yn)
315 {
316         if (_port_handle) {
317                 port_engine.ensure_input_monitoring (_port_handle, yn);
318         }
319 }
320
321 bool
322 Port::monitoring_input () const
323 {
324         if (_port_handle) {
325                 return port_engine.monitoring_input (_port_handle);
326         }
327         return false;
328 }
329
330 void
331 Port::reset ()
332 {
333         _last_monitor = false;
334 }
335
336 void
337 Port::cycle_start (pframes_t)
338 {
339         _port_buffer_offset = 0;
340 }
341
342 void
343 Port::increment_port_buffer_offset (pframes_t nframes)
344 {
345         _port_buffer_offset += nframes;
346 }
347
348 void
349 Port::set_public_latency_range (LatencyRange& range, bool playback) const
350 {
351         /* this sets the visible latency that the rest of the port system
352            sees. because we do latency compensation, all (most) of our visible
353            port latency values are identical.
354         */
355
356         DEBUG_TRACE (DEBUG::Latency,
357                      string_compose ("SET PORT %1 %4 PUBLIC latency now [%2 - %3]\n",
358                                      name(), range.min, range.max,
359                                      (playback ? "PLAYBACK" : "CAPTURE")));;
360
361         if (_port_handle) {
362                 port_engine.set_latency_range (_port_handle, playback, range);
363         }
364 }
365
366 void
367 Port::set_private_latency_range (LatencyRange& range, bool playback)
368 {
369         if (playback) {
370                 _private_playback_latency = range;
371                 DEBUG_TRACE (DEBUG::Latency, string_compose (
372                                      "SET PORT %1 playback PRIVATE latency now [%2 - %3]\n",
373                                      name(),
374                                      _private_playback_latency.min,
375                                      _private_playback_latency.max));
376         } else {
377                 _private_capture_latency = range;
378                 DEBUG_TRACE (DEBUG::Latency, string_compose (
379                                      "SET PORT %1 capture PRIVATE latency now [%2 - %3]\n",
380                                      name(),
381                                      _private_capture_latency.min,
382                                      _private_capture_latency.max));
383         }
384
385         /* push to public (port system) location so that everyone else can see it */
386
387         set_public_latency_range (range, playback);
388 }
389
390 const LatencyRange&
391 Port::private_latency_range (bool playback) const
392 {
393         if (playback) {
394                 DEBUG_TRACE (DEBUG::Latency, string_compose (
395                                      "GET PORT %1 playback PRIVATE latency now [%2 - %3]\n",
396                                      name(),
397                                      _private_playback_latency.min,
398                                      _private_playback_latency.max));
399                 return _private_playback_latency;
400         } else {
401                 DEBUG_TRACE (DEBUG::Latency, string_compose (
402                                      "GET PORT %1 capture PRIVATE latency now [%2 - %3]\n",
403                                      name(),
404                                      _private_playback_latency.min,
405                                      _private_playback_latency.max));
406                 return _private_capture_latency;
407         }
408 }
409
410 LatencyRange
411 Port::public_latency_range (bool /*playback*/) const
412 {
413         LatencyRange r;
414
415
416         if (_port_handle) {
417                 r = port_engine.get_latency_range (_port_handle, sends_output() ? true : false);
418
419                 DEBUG_TRACE (DEBUG::Latency, string_compose (
420                                      "GET PORT %1: %4 PUBLIC latency range %2 .. %3\n",
421                                      name(), r.min, r.max,
422                                      sends_output() ? "PLAYBACK" : "CAPTURE"));
423         }
424
425         return r;
426 }
427
428 void
429 Port::get_connected_latency_range (LatencyRange& range, bool playback) const
430 {
431         vector<string> connections;
432
433         get_connections (connections);
434
435         if (!connections.empty()) {
436
437                 range.min = ~((pframes_t) 0);
438                 range.max = 0;
439
440                 DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: %2 connections to check for latency range\n", name(), connections.size()));
441
442                 for (vector<string>::const_iterator c = connections.begin();
443                      c != connections.end(); ++c) {
444
445                         LatencyRange lr;
446
447                         if (!AudioEngine::instance()->port_is_mine (*c)) {
448
449                                 /* port belongs to some other port-system client, use
450                                  * the port engine to lookup its latency information.
451                                  */
452
453                                 PortEngine::PortHandle remote_port = port_engine.get_port_by_name (*c);
454
455                                 if (remote_port) {
456                                         lr = port_engine.get_latency_range (remote_port, playback);
457
458                                         DEBUG_TRACE (DEBUG::Latency, string_compose (
459                                                              "\t%1 <-> %2 : latter has latency range %3 .. %4\n",
460                                                              name(), *c, lr.min, lr.max));
461
462                                         range.min = min (range.min, lr.min);
463                                         range.max = max (range.max, lr.max);
464                                 }
465
466                         } else {
467
468                                 /* port belongs to this instance of ardour,
469                                    so look up its latency information
470                                    internally, because our published/public
471                                    values already contain our plugin
472                                    latency compensation.
473                                 */
474
475                                 boost::shared_ptr<Port> remote_port = AudioEngine::instance()->get_port_by_name (*c);
476                                 if (remote_port) {
477                                         lr = remote_port->private_latency_range ((playback ? true : false));
478                                         DEBUG_TRACE (DEBUG::Latency, string_compose (
479                                                              "\t%1 <-LOCAL-> %2 : latter has latency range %3 .. %4\n",
480                                                              name(), *c, lr.min, lr.max));
481
482                                         range.min = min (range.min, lr.min);
483                                         range.max = max (range.max, lr.max);
484                                 }
485                         }
486                 }
487
488         } else {
489                 DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: not connected to anything\n", name()));
490                 range.min = 0;
491                 range.max = 0;
492         }
493
494         DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: final connected latency range [ %2 .. %3 ] \n", name(), range.min, range.max));
495 }
496
497 int
498 Port::reestablish ()
499 {
500         DEBUG_TRACE (DEBUG::Ports, string_compose ("re-establish %1 port %2\n", type().to_string(), _name));
501         _port_handle = port_engine.register_port (_name, type(), _flags);
502
503         if (_port_handle == 0) {
504                 PBD::error << string_compose (_("could not reregister %1"), _name) << endmsg;
505                 return -1;
506         }
507
508         reset ();
509
510         port_manager->PortConnectedOrDisconnected.connect_same_thread (engine_connection,
511                         boost::bind (&Port::port_connected_or_disconnected, this, _1, _3, _5));
512         return 0;
513 }
514
515
516 int
517 Port::reconnect ()
518 {
519         /* caller must hold process lock; intended to be used only after reestablish() */
520
521         DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2 destinations\n",name(), _connections.size()));
522
523         for (std::set<string>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
524                 if (connect (*i)) {
525                         return -1;
526                 }
527         }
528
529         return 0;
530 }
531
532 /** @param n Short port name (no port-system client name) */
533 int
534 Port::set_name (std::string const & n)
535 {
536         if (n == _name || !_port_handle) {
537                 return 0;
538         }
539
540         int const r = port_engine.set_port_name (_port_handle, n);
541
542         if (r == 0) {
543                 AudioEngine::instance()->port_renamed (_name, n);
544                 _name = n;
545         }
546
547
548         return r;
549 }
550
551 bool
552 Port::physically_connected () const
553 {
554         if (!_port_handle) {
555                 return false;
556         }
557
558         return port_engine.physically_connected (_port_handle);
559 }
560
561 XMLNode&
562 Port::get_state () const
563 {
564         XMLNode* root = new XMLNode (state_node_name);
565
566         root->add_property (X_("name"), AudioEngine::instance()->make_port_name_relative (name()));
567
568         if (receives_input()) {
569                 root->add_property (X_("direction"), X_("input"));
570         } else {
571                 root->add_property (X_("direction"), X_("output"));
572         }
573
574         vector<string> c;
575
576         get_connections (c);
577
578         for (vector<string>::const_iterator i = c.begin(); i != c.end(); ++i) {
579                 XMLNode* child = new XMLNode (X_("Connection"));
580                 child->add_property (X_("other"), *i);
581                 root->add_child_nocopy (*child);
582         }
583
584         return *root;
585 }
586
587 int
588 Port::set_state (const XMLNode& node, int)
589 {
590         XMLProperty const * prop;
591
592         if (node.name() != state_node_name) {
593                 return -1;
594         }
595
596         if ((prop = node.property (X_("name"))) != 0) {
597                 set_name (prop->value());
598         }
599
600         const XMLNodeList& children (node.children());
601
602         _connections.clear ();
603
604         for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
605
606                 if ((*c)->name() != X_("Connection")) {
607                         continue;
608                 }
609
610                 if ((prop = (*c)->property (X_("other"))) == 0) {
611                         continue;
612                 }
613
614                 _connections.insert (prop->value());
615         }
616
617         return 0;
618 }