c6b2c0b47d9c5c71a5bb30e7668b5ba93fba294b
[ardour.git] / libs / ardour / port_manager.cc
1 /*
2     Copyright (C) 2013 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 "pbd/convert.h"
21 #include "pbd/error.h"
22
23 #include "ardour/async_midi_port.h"
24 #include "ardour/audio_backend.h"
25 #include "ardour/audio_port.h"
26 #include "ardour/debug.h"
27 #include "ardour/midi_port.h"
28 #include "ardour/midiport_manager.h"
29 #include "ardour/port_manager.h"
30 #include "ardour/profile.h"
31 #include "ardour/session.h"
32
33 #include "pbd/i18n.h"
34
35 using namespace ARDOUR;
36 using namespace PBD;
37 using std::string;
38 using std::vector;
39
40 PortManager::PortManager ()
41         : ports (new Ports)
42         , _port_remove_in_progress (false)
43 {
44 }
45
46 void
47 PortManager::remove_all_ports ()
48 {
49         /* make sure that JACK callbacks that will be invoked as we cleanup
50          * ports know that they have nothing to do.
51          */
52
53         _port_remove_in_progress = true;
54
55         /* process lock MUST be held by caller
56         */
57
58         {
59                 RCUWriter<Ports> writer (ports);
60                 boost::shared_ptr<Ports> ps = writer.get_copy ();
61                 ps->clear ();
62         }
63
64         /* clear dead wood list in RCU */
65
66         ports.flush ();
67
68         _port_remove_in_progress = false;
69 }
70
71
72 string
73 PortManager::make_port_name_relative (const string& portname) const
74 {
75         if (!_backend) {
76                 return portname;
77         }
78
79         string::size_type colon = portname.find (':');
80
81         if (colon == string::npos) {
82                 return portname;
83         }
84
85         if (portname.substr (0, colon) == _backend->my_name()) {
86                 return portname.substr (colon+1);
87         }
88
89         return portname;
90 }
91
92 string
93 PortManager::make_port_name_non_relative (const string& portname) const
94 {
95         string str;
96
97         if (portname.find_first_of (':') != string::npos) {
98                 return portname;
99         }
100
101         str  = _backend->my_name();
102         str += ':';
103         str += portname;
104
105         return str;
106 }
107
108 std::string
109 PortManager::get_pretty_name_by_name(const std::string& portname) const
110 {
111         PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
112         if (ph) {
113                 std::string value;
114                 std::string type;
115                 if (0 == _backend->get_port_property (ph,
116                                         "http://jackaudio.org/metadata/pretty-name",
117                                         value, type))
118                 {
119                         return value;
120                 }
121         }
122         return "";
123 }
124
125 bool
126 PortManager::port_is_mine (const string& portname) const
127 {
128         if (!_backend) {
129                 return true;
130         }
131
132         string self = _backend->my_name();
133
134         if (portname.find_first_of (':') != string::npos) {
135                 if (portname.substr (0, self.length ()) != self) {
136                         return false;
137                 }
138         }
139
140         return true;
141 }
142
143 bool
144 PortManager::port_is_physical (const std::string& portname) const
145 {
146         if (!_backend) {
147                 return false;
148         }
149
150         PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
151         if (!ph) {
152                 return false;
153         }
154
155         return _backend->port_is_physical (ph);
156 }
157
158 void
159 PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s)
160 {
161         if (!_backend) {
162                 s.clear ();
163                 return;
164         }
165         _backend->get_physical_outputs (type, s);
166 }
167
168 void
169 PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s)
170 {
171         if (!_backend) {
172                 s.clear ();
173                 return;
174         }
175
176         _backend->get_physical_inputs (type, s);
177 }
178
179 ChanCount
180 PortManager::n_physical_outputs () const
181 {
182         if (!_backend) {
183                 return ChanCount::ZERO;
184         }
185
186         return _backend->n_physical_outputs ();
187 }
188
189 ChanCount
190 PortManager::n_physical_inputs () const
191 {
192         if (!_backend) {
193                 return ChanCount::ZERO;
194         }
195         return _backend->n_physical_inputs ();
196 }
197
198 /** @param name Full or short name of port
199  *  @return Corresponding Port or 0.
200  */
201
202 boost::shared_ptr<Port>
203 PortManager::get_port_by_name (const string& portname)
204 {
205         if (!_backend) {
206                 return boost::shared_ptr<Port>();
207         }
208
209         if (!port_is_mine (portname)) {
210                 /* not an ardour port */
211                 return boost::shared_ptr<Port> ();
212         }
213
214         boost::shared_ptr<Ports> pr = ports.reader();
215         std::string rel = make_port_name_relative (portname);
216         Ports::iterator x = pr->find (rel);
217
218         if (x != pr->end()) {
219                 /* its possible that the port was renamed by some 3rd party and
220                    we don't know about it. check for this (the check is quick
221                    and cheap), and if so, rename the port (which will alter
222                    the port map as a side effect).
223                 */
224                 const std::string check = make_port_name_relative (_backend->get_port_name (x->second->port_handle()));
225                 if (check != rel) {
226                         x->second->set_name (check);
227                 }
228                 return x->second;
229         }
230
231         return boost::shared_ptr<Port> ();
232 }
233
234 void
235 PortManager::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
236 {
237         RCUWriter<Ports> writer (ports);
238         boost::shared_ptr<Ports> p = writer.get_copy();
239         Ports::iterator x = p->find (old_relative_name);
240
241         if (x != p->end()) {
242                 boost::shared_ptr<Port> port = x->second;
243                 p->erase (x);
244                 p->insert (make_pair (new_relative_name, port));
245         }
246 }
247
248 int
249 PortManager::get_ports (DataType type, PortList& pl)
250 {
251         boost::shared_ptr<Ports> plist = ports.reader();
252         for (Ports::iterator p = plist->begin(); p != plist->end(); ++p) {
253                 if (p->second->type() == type) {
254                         pl.push_back (p->second);
255                 }
256         }
257         return pl.size();
258 }
259
260 int
261 PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
262 {
263         s.clear();
264
265         if (!_backend) {
266                 return 0;
267         }
268
269         return _backend->get_ports (port_name_pattern, type, flags, s);
270 }
271
272 void
273 PortManager::port_registration_failure (const std::string& portname)
274 {
275         if (!_backend) {
276                 return;
277         }
278
279         string full_portname = _backend->my_name();
280         full_portname += ':';
281         full_portname += portname;
282
283
284         PortEngine::PortHandle p = _backend->get_port_by_name (full_portname);
285         string reason;
286
287         if (p) {
288                 reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
289         } else {
290                 reason = string_compose (_("No more ports are available. You will need to stop %1 and restart with more ports if you need this many tracks."), PROGRAM_NAME);
291         }
292
293         throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
294 }
295
296 boost::shared_ptr<Port>
297 PortManager::register_port (DataType dtype, const string& portname, bool input, bool async, PortFlags flags)
298 {
299         boost::shared_ptr<Port> newport;
300
301         /* limit the possible flags that can be set */
302
303         flags = PortFlags (flags & (Hidden|Shadow|IsTerminal));
304
305         try {
306                 if (dtype == DataType::AUDIO) {
307                         DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
308                                                                    portname, input));
309                         newport.reset (new AudioPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)));
310                 } else if (dtype == DataType::MIDI) {
311                         if (async) {
312                                 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
313                                                                            portname, input));
314                                 newport.reset (new AsyncMIDIPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)));
315                         } else {
316                                 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
317                                                                            portname, input));
318                                 newport.reset (new MidiPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)));
319                         }
320                 } else {
321                         throw PortRegistrationFailure("unable to create port (unknown type)");
322                 }
323
324                 RCUWriter<Ports> writer (ports);
325                 boost::shared_ptr<Ports> ps = writer.get_copy ();
326                 ps->insert (make_pair (make_port_name_relative (portname), newport));
327
328                 /* writer goes out of scope, forces update */
329
330         }
331
332         catch (PortRegistrationFailure& err) {
333                 throw err;
334         } catch (std::exception& e) {
335                 throw PortRegistrationFailure(string_compose(
336                                 _("unable to create port: %1"), e.what()).c_str());
337         } catch (...) {
338                 throw PortRegistrationFailure("unable to create port (unknown error)");
339         }
340
341         DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
342         return newport;
343 }
344
345 boost::shared_ptr<Port>
346 PortManager::register_input_port (DataType type, const string& portname, bool async, PortFlags extra_flags)
347 {
348         return register_port (type, portname, true, async, extra_flags);
349 }
350
351 boost::shared_ptr<Port>
352 PortManager::register_output_port (DataType type, const string& portname, bool async, PortFlags extra_flags)
353 {
354         return register_port (type, portname, false, async, extra_flags);
355 }
356
357 int
358 PortManager::unregister_port (boost::shared_ptr<Port> port)
359 {
360         /* This is a little subtle. We do not call the backend's port
361          * unregistration code from here. That is left for the Port
362          * destructor. We are trying to drop references to the Port object
363          * here, so that its destructor will run and it will unregister itself.
364          */
365
366         /* caller must hold process lock */
367
368         {
369                 RCUWriter<Ports> writer (ports);
370                 boost::shared_ptr<Ports> ps = writer.get_copy ();
371                 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
372
373                 if (x != ps->end()) {
374                         ps->erase (x);
375                 }
376
377                 /* writer goes out of scope, forces update */
378         }
379
380         ports.flush ();
381
382         return 0;
383 }
384
385 bool
386 PortManager::connected (const string& port_name)
387 {
388         if (!_backend) {
389                 return false;
390         }
391
392         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
393
394         if (!handle) {
395                 return false;
396         }
397
398         return _backend->connected (handle);
399 }
400
401 bool
402 PortManager::physically_connected (const string& port_name)
403 {
404         if (!_backend) {
405                 return false;
406         }
407
408         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
409
410         if (!handle) {
411                 return false;
412         }
413
414         return _backend->physically_connected (handle);
415 }
416
417 int
418 PortManager::get_connections (const string& port_name, std::vector<std::string>& s)
419 {
420         if (!_backend) {
421                 s.clear ();
422                 return 0;
423         }
424
425         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
426
427         if (!handle) {
428                 s.clear ();
429                 return 0;
430         }
431
432         return _backend->get_connections (handle, s);
433 }
434
435 int
436 PortManager::connect (const string& source, const string& destination)
437 {
438         int ret;
439
440         string s = make_port_name_non_relative (source);
441         string d = make_port_name_non_relative (destination);
442
443         boost::shared_ptr<Port> src = get_port_by_name (s);
444         boost::shared_ptr<Port> dst = get_port_by_name (d);
445
446         if (src) {
447                 ret = src->connect (d);
448         } else if (dst) {
449                 ret = dst->connect (s);
450         } else {
451                 /* neither port is known to us ...hand-off to the PortEngine
452                  */
453                 if (_backend) {
454                         ret = _backend->connect (s, d);
455                 } else {
456                         ret = -1;
457                 }
458         }
459
460         if (ret > 0) {
461                 /* already exists - no error, no warning */
462         } else if (ret < 0) {
463                 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
464                                         source, s, destination, d)
465                       << endmsg;
466         }
467
468         return ret;
469 }
470
471 int
472 PortManager::disconnect (const string& source, const string& destination)
473 {
474         int ret;
475
476         string s = make_port_name_non_relative (source);
477         string d = make_port_name_non_relative (destination);
478
479         boost::shared_ptr<Port> src = get_port_by_name (s);
480         boost::shared_ptr<Port> dst = get_port_by_name (d);
481
482         if (src) {
483                 ret = src->disconnect (d);
484         } else if (dst) {
485                 ret = dst->disconnect (s);
486         } else {
487                 /* neither port is known to us ...hand-off to the PortEngine
488                  */
489                 if (_backend) {
490                         ret = _backend->disconnect (s, d);
491                 } else {
492                         ret = -1;
493                 }
494         }
495         return ret;
496 }
497
498 int
499 PortManager::disconnect (boost::shared_ptr<Port> port)
500 {
501         return port->disconnect_all ();
502 }
503
504 int
505 PortManager::reestablish_ports ()
506 {
507         Ports::iterator i;
508
509         boost::shared_ptr<Ports> p = ports.reader ();
510
511         DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
512
513         for (i = p->begin(); i != p->end(); ++i) {
514                 if (i->second->reestablish ()) {
515                         error << string_compose (_("Re-establising port %1 failed"), i->second->name()) << endmsg;
516                         std::cerr << string_compose (_("Re-establising port %1 failed"), i->second->name()) << std::endl;
517                         break;
518                 }
519         }
520
521         if (i != p->end()) {
522                 /* failed */
523                 remove_all_ports ();
524                 return -1;
525         }
526
527         return 0;
528 }
529
530 int
531 PortManager::reconnect_ports ()
532 {
533         boost::shared_ptr<Ports> p = ports.reader ();
534
535         if (!Profile->get_trx()) {
536                 /* re-establish connections */
537
538                 DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
539
540                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
541                         i->second->reconnect ();
542                 }
543         }
544
545         return 0;
546 }
547
548 void
549 PortManager::connect_callback (const string& a, const string& b, bool conn)
550 {
551         boost::shared_ptr<Port> port_a;
552         boost::shared_ptr<Port> port_b;
553         Ports::iterator x;
554         boost::shared_ptr<Ports> pr = ports.reader ();
555
556         x = pr->find (make_port_name_relative (a));
557         if (x != pr->end()) {
558                 port_a = x->second;
559         }
560
561         x = pr->find (make_port_name_relative (b));
562         if (x != pr->end()) {
563                 port_b = x->second;
564         }
565
566         PortConnectedOrDisconnected (
567                 port_a, a,
568                 port_b, b,
569                 conn
570                 ); /* EMIT SIGNAL */
571 }
572
573 void
574 PortManager::registration_callback ()
575 {
576         if (!_port_remove_in_progress) {
577                 PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
578         }
579 }
580
581 bool
582 PortManager::can_request_input_monitoring () const
583 {
584         if (!_backend) {
585                 return false;
586         }
587
588         return _backend->can_monitor_input ();
589 }
590
591 void
592 PortManager::request_input_monitoring (const string& name, bool yn) const
593 {
594         if (!_backend) {
595                 return;
596         }
597
598         PortEngine::PortHandle ph = _backend->get_port_by_name (name);
599
600         if (ph) {
601                 _backend->request_input_monitoring (ph, yn);
602         }
603 }
604
605 void
606 PortManager::ensure_input_monitoring (const string& name, bool yn) const
607 {
608         if (!_backend) {
609                 return;
610         }
611
612         PortEngine::PortHandle ph = _backend->get_port_by_name (name);
613
614         if (ph) {
615                 _backend->ensure_input_monitoring (ph, yn);
616         }
617 }
618
619 uint32_t
620 PortManager::port_name_size() const
621 {
622         if (!_backend) {
623                 return 0;
624         }
625
626         return _backend->port_name_size ();
627 }
628
629 string
630 PortManager::my_name() const
631 {
632         if (!_backend) {
633                 return string();
634         }
635
636         return _backend->my_name();
637 }
638
639 int
640 PortManager::graph_order_callback ()
641 {
642         if (!_port_remove_in_progress) {
643                 GraphReordered(); /* EMIT SIGNAL */
644         }
645
646         return 0;
647 }
648
649 void
650 PortManager::cycle_start (pframes_t nframes)
651 {
652         Port::set_global_port_buffer_offset (0);
653         Port::set_cycle_framecnt (nframes);
654
655         _cycle_ports = ports.reader ();
656
657         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
658                 p->second->cycle_start (nframes);
659         }
660 }
661
662 void
663 PortManager::cycle_end (pframes_t nframes)
664 {
665         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
666                 p->second->cycle_end (nframes);
667         }
668
669         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
670                 p->second->flush_buffers (nframes);
671         }
672
673         _cycle_ports.reset ();
674
675         /* we are done */
676 }
677
678 void
679 PortManager::silence (pframes_t nframes, Session *s)
680 {
681         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
682                 if (s && i->second == s->mtc_output_port ()) {
683                         continue;
684                 }
685                 if (s && i->second == s->midi_clock_output_port ()) {
686                         continue;
687                 }
688                 if (s && i->second == s->ltc_output_port ()) {
689                         continue;
690                 }
691                 if (boost::dynamic_pointer_cast<AsyncMIDIPort>(i->second)) {
692                         continue;
693                 }
694                 if (i->second->sends_output()) {
695                         i->second->get_buffer(nframes).silence(nframes);
696                 }
697         }
698 }
699
700 void
701 PortManager::silence_outputs (pframes_t nframes)
702 {
703         std::vector<std::string> port_names;
704         if (get_ports("", DataType::AUDIO, IsOutput, port_names)) {
705                 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
706                         if (!port_is_mine(*p)) {
707                                 continue;
708                         }
709                         PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
710                         if (!ph) {
711                                 continue;
712                         }
713                         void *buf = _backend->get_buffer(ph, nframes);
714                         if (!buf) {
715                                 continue;
716                         }
717                         memset (buf, 0, sizeof(float) * nframes);
718                 }
719         }
720
721         if (get_ports("", DataType::MIDI, IsOutput, port_names)) {
722                 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
723                         if (!port_is_mine(*p)) {
724                                 continue;
725                         }
726                         PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
727                         if (!ph) {
728                                 continue;
729                         }
730                         void *buf = _backend->get_buffer(ph, nframes);
731                         if (!buf) {
732                                 continue;
733                         }
734                         _backend->midi_clear (buf);
735                 }
736         }
737 }
738
739 void
740 PortManager::check_monitoring ()
741 {
742         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
743
744                 bool x;
745
746                 if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
747                         i->second->set_last_monitor (x);
748                         /* XXX I think this is dangerous, due to
749                            a likely mutex in the signal handlers ...
750                         */
751                         i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
752                 }
753         }
754 }
755
756 void
757 PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
758 {
759         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
760
761                 if (i->second->sends_output()) {
762
763                         boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
764                         if (ap) {
765                                 Sample* s = ap->engine_get_whole_audio_buffer ();
766                                 gain_t g = base_gain;
767
768                                 for (pframes_t n = 0; n < nframes; ++n) {
769                                         *s++ *= g;
770                                         g -= gain_step;
771                                 }
772                         }
773                 }
774         }
775 }
776
777 PortEngine&
778 PortManager::port_engine()
779 {
780         assert (_backend);
781         return *_backend;
782 }