enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[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)
298 {
299         boost::shared_ptr<Port> newport;
300
301         try {
302                 if (dtype == DataType::AUDIO) {
303                         DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
304                                                                    portname, input));
305                         newport.reset (new AudioPort (portname, (input ? IsInput : IsOutput)));
306                 } else if (dtype == DataType::MIDI) {
307                         if (async) {
308                                 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
309                                                                            portname, input));
310                                 newport.reset (new AsyncMIDIPort (portname, (input ? IsInput : IsOutput)));
311                         } else {
312                                 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
313                                                                            portname, input));
314                                 newport.reset (new MidiPort (portname, (input ? IsInput : IsOutput)));
315                         }
316                 } else {
317                         throw PortRegistrationFailure("unable to create port (unknown type)");
318                 }
319
320                 RCUWriter<Ports> writer (ports);
321                 boost::shared_ptr<Ports> ps = writer.get_copy ();
322                 ps->insert (make_pair (make_port_name_relative (portname), newport));
323
324                 /* writer goes out of scope, forces update */
325
326         }
327
328         catch (PortRegistrationFailure& err) {
329                 throw err;
330         } catch (std::exception& e) {
331                 throw PortRegistrationFailure(string_compose(
332                                 _("unable to create port: %1"), e.what()).c_str());
333         } catch (...) {
334                 throw PortRegistrationFailure("unable to create port (unknown error)");
335         }
336
337         DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
338         return newport;
339 }
340
341 boost::shared_ptr<Port>
342 PortManager::register_input_port (DataType type, const string& portname, bool async)
343 {
344         return register_port (type, portname, true, async);
345 }
346
347 boost::shared_ptr<Port>
348 PortManager::register_output_port (DataType type, const string& portname, bool async)
349 {
350         return register_port (type, portname, false, async);
351 }
352
353 int
354 PortManager::unregister_port (boost::shared_ptr<Port> port)
355 {
356         /* caller must hold process lock */
357
358         {
359                 RCUWriter<Ports> writer (ports);
360                 boost::shared_ptr<Ports> ps = writer.get_copy ();
361                 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
362
363                 if (x != ps->end()) {
364                         ps->erase (x);
365                 }
366
367                 /* writer goes out of scope, forces update */
368         }
369
370         ports.flush ();
371
372         return 0;
373 }
374
375 bool
376 PortManager::connected (const string& port_name)
377 {
378         if (!_backend) {
379                 return false;
380         }
381
382         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
383
384         if (!handle) {
385                 return false;
386         }
387
388         return _backend->connected (handle);
389 }
390
391 bool
392 PortManager::physically_connected (const string& port_name)
393 {
394         if (!_backend) {
395                 return false;
396         }
397
398         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
399
400         if (!handle) {
401                 return false;
402         }
403
404         return _backend->physically_connected (handle);
405 }
406
407 int
408 PortManager::get_connections (const string& port_name, std::vector<std::string>& s)
409 {
410         if (!_backend) {
411                 s.clear ();
412                 return 0;
413         }
414
415         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
416
417         if (!handle) {
418                 s.clear ();
419                 return 0;
420         }
421
422         return _backend->get_connections (handle, s);
423 }
424
425 int
426 PortManager::connect (const string& source, const string& destination)
427 {
428         int ret;
429
430         string s = make_port_name_non_relative (source);
431         string d = make_port_name_non_relative (destination);
432
433         boost::shared_ptr<Port> src = get_port_by_name (s);
434         boost::shared_ptr<Port> dst = get_port_by_name (d);
435
436         if (src) {
437                 ret = src->connect (d);
438         } else if (dst) {
439                 ret = dst->connect (s);
440         } else {
441                 /* neither port is known to us ...hand-off to the PortEngine
442                  */
443                 if (_backend) {
444                         ret = _backend->connect (s, d);
445                 } else {
446                         ret = -1;
447                 }
448         }
449
450         if (ret > 0) {
451                 /* already exists - no error, no warning */
452         } else if (ret < 0) {
453                 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
454                                         source, s, destination, d)
455                       << endmsg;
456         }
457
458         return ret;
459 }
460
461 int
462 PortManager::disconnect (const string& source, const string& destination)
463 {
464         int ret;
465
466         string s = make_port_name_non_relative (source);
467         string d = make_port_name_non_relative (destination);
468
469         boost::shared_ptr<Port> src = get_port_by_name (s);
470         boost::shared_ptr<Port> dst = get_port_by_name (d);
471
472         if (src) {
473                 ret = src->disconnect (d);
474         } else if (dst) {
475                 ret = dst->disconnect (s);
476         } else {
477                 /* neither port is known to us ...hand-off to the PortEngine
478                  */
479                 if (_backend) {
480                         ret = _backend->disconnect (s, d);
481                 } else {
482                         ret = -1;
483                 }
484         }
485         return ret;
486 }
487
488 int
489 PortManager::disconnect (boost::shared_ptr<Port> port)
490 {
491         return port->disconnect_all ();
492 }
493
494 int
495 PortManager::reestablish_ports ()
496 {
497         Ports::iterator i;
498
499         boost::shared_ptr<Ports> p = ports.reader ();
500
501         DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
502
503         for (i = p->begin(); i != p->end(); ++i) {
504                 if (i->second->reestablish ()) {
505                         error << string_compose (_("Re-establising port %1 failed"), i->second->name()) << endmsg;
506                         std::cerr << string_compose (_("Re-establising port %1 failed"), i->second->name()) << std::endl;
507                         break;
508                 }
509         }
510
511         if (i != p->end()) {
512                 /* failed */
513                 remove_all_ports ();
514                 return -1;
515         }
516
517         return 0;
518 }
519
520 int
521 PortManager::reconnect_ports ()
522 {
523         boost::shared_ptr<Ports> p = ports.reader ();
524
525         if (!Profile->get_trx()) {
526                 /* re-establish connections */
527
528                 DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
529
530                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
531                         i->second->reconnect ();
532                 }
533         }
534
535         return 0;
536 }
537
538 void
539 PortManager::connect_callback (const string& a, const string& b, bool conn)
540 {
541         boost::shared_ptr<Port> port_a;
542         boost::shared_ptr<Port> port_b;
543         Ports::iterator x;
544         boost::shared_ptr<Ports> pr = ports.reader ();
545
546         x = pr->find (make_port_name_relative (a));
547         if (x != pr->end()) {
548                 port_a = x->second;
549         }
550
551         x = pr->find (make_port_name_relative (b));
552         if (x != pr->end()) {
553                 port_b = x->second;
554         }
555
556         PortConnectedOrDisconnected (
557                 port_a, a,
558                 port_b, b,
559                 conn
560                 ); /* EMIT SIGNAL */
561 }
562
563 void
564 PortManager::registration_callback ()
565 {
566         if (!_port_remove_in_progress) {
567                 PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
568         }
569 }
570
571 bool
572 PortManager::can_request_input_monitoring () const
573 {
574         if (!_backend) {
575                 return false;
576         }
577
578         return _backend->can_monitor_input ();
579 }
580
581 void
582 PortManager::request_input_monitoring (const string& name, bool yn) const
583 {
584         if (!_backend) {
585                 return;
586         }
587
588         PortEngine::PortHandle ph = _backend->get_port_by_name (name);
589
590         if (ph) {
591                 _backend->request_input_monitoring (ph, yn);
592         }
593 }
594
595 void
596 PortManager::ensure_input_monitoring (const string& name, bool yn) const
597 {
598         if (!_backend) {
599                 return;
600         }
601
602         PortEngine::PortHandle ph = _backend->get_port_by_name (name);
603
604         if (ph) {
605                 _backend->ensure_input_monitoring (ph, yn);
606         }
607 }
608
609 uint32_t
610 PortManager::port_name_size() const
611 {
612         if (!_backend) {
613                 return 0;
614         }
615
616         return _backend->port_name_size ();
617 }
618
619 string
620 PortManager::my_name() const
621 {
622         if (!_backend) {
623                 return string();
624         }
625
626         return _backend->my_name();
627 }
628
629 int
630 PortManager::graph_order_callback ()
631 {
632         if (!_port_remove_in_progress) {
633                 GraphReordered(); /* EMIT SIGNAL */
634         }
635
636         return 0;
637 }
638
639 void
640 PortManager::cycle_start (pframes_t nframes)
641 {
642         Port::set_global_port_buffer_offset (0);
643         Port::set_cycle_framecnt (nframes);
644
645         _cycle_ports = ports.reader ();
646
647         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
648                 p->second->cycle_start (nframes);
649         }
650 }
651
652 void
653 PortManager::cycle_end (pframes_t nframes)
654 {
655         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
656                 p->second->cycle_end (nframes);
657         }
658
659         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
660                 p->second->flush_buffers (nframes);
661         }
662
663         _cycle_ports.reset ();
664
665         /* we are done */
666 }
667
668 void
669 PortManager::silence (pframes_t nframes, Session *s)
670 {
671         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
672                 if (s && i->second == s->mtc_output_port ()) {
673                         continue;
674                 }
675                 if (s && i->second == s->midi_clock_output_port ()) {
676                         continue;
677                 }
678                 if (s && i->second == s->ltc_output_port ()) {
679                         continue;
680                 }
681                 if (i->second->sends_output()) {
682                         i->second->get_buffer(nframes).silence(nframes);
683                 }
684         }
685 }
686
687 void
688 PortManager::silence_outputs (pframes_t nframes)
689 {
690         std::vector<std::string> port_names;
691         if (get_ports("", DataType::AUDIO, IsOutput, port_names)) {
692                 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
693                         if (!port_is_mine(*p)) {
694                                 continue;
695                         }
696                         PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
697                         if (!ph) {
698                                 continue;
699                         }
700                         void *buf = _backend->get_buffer(ph, nframes);
701                         if (!buf) {
702                                 continue;
703                         }
704                         memset (buf, 0, sizeof(float) * nframes);
705                 }
706         }
707
708         if (get_ports("", DataType::MIDI, IsOutput, port_names)) {
709                 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
710                         if (!port_is_mine(*p)) {
711                                 continue;
712                         }
713                         PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
714                         if (!ph) {
715                                 continue;
716                         }
717                         void *buf = _backend->get_buffer(ph, nframes);
718                         if (!buf) {
719                                 continue;
720                         }
721                         _backend->midi_clear (buf);
722                 }
723         }
724 }
725
726 void
727 PortManager::check_monitoring ()
728 {
729         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
730
731                 bool x;
732
733                 if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
734                         i->second->set_last_monitor (x);
735                         /* XXX I think this is dangerous, due to
736                            a likely mutex in the signal handlers ...
737                         */
738                         i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
739                 }
740         }
741 }
742
743 void
744 PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
745 {
746         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
747
748                 if (i->second->sends_output()) {
749
750                         boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
751                         if (ap) {
752                                 Sample* s = ap->engine_get_whole_audio_buffer ();
753                                 gain_t g = base_gain;
754
755                                 for (pframes_t n = 0; n < nframes; ++n) {
756                                         *s++ *= g;
757                                         g -= gain_step;
758                                 }
759                         }
760                 }
761         }
762 }
763
764 PortEngine&
765 PortManager::port_engine()
766 {
767         assert (_backend);
768         return *_backend;
769 }