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