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