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