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