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