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