b99337a891dc831decadd74a3cb1bfb771f9f479
[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 #ifdef COMPILER_MSVC
21 #include <io.h> // Microsoft's nearest equivalent to <unistd.h>
22 #include <ardourext/misc.h>
23 #else
24 #include <regex.h>
25 #endif
26
27 #include <glibmm/fileutils.h>
28 #include <glibmm/miscutils.h>
29
30 #include "pbd/convert.h"
31 #include "pbd/error.h"
32
33 #include "ardour/async_midi_port.h"
34 #include "ardour/audio_backend.h"
35 #include "ardour/audio_port.h"
36 #include "ardour/debug.h"
37 #include "ardour/filesystem_paths.h"
38 #include "ardour/midi_port.h"
39 #include "ardour/midiport_manager.h"
40 #include "ardour/port_manager.h"
41 #include "ardour/profile.h"
42 #include "ardour/session.h"
43
44 #include "pbd/i18n.h"
45
46 using namespace ARDOUR;
47 using namespace PBD;
48 using std::string;
49 using std::vector;
50
51 PortManager::PortManager ()
52         : ports (new Ports)
53         , _port_remove_in_progress (false)
54         , _port_deletions_pending (8192) /* ick, arbitrary sizing */
55         , midi_info_dirty (true)
56 {
57         load_midi_port_info ();
58 }
59
60 void
61 PortManager::clear_pending_port_deletions ()
62 {
63         Port* p;
64
65         DEBUG_TRACE (DEBUG::Ports, string_compose ("pending port deletions: %1\n", _port_deletions_pending.read_space()));
66
67         while (_port_deletions_pending.read (&p, 1) == 1) {
68                 delete p;
69         }
70 }
71
72 void
73 PortManager::remove_all_ports ()
74 {
75         /* make sure that JACK callbacks that will be invoked as we cleanup
76          * ports know that they have nothing to do.
77          */
78
79         _port_remove_in_progress = true;
80
81         /* process lock MUST be held by caller
82         */
83
84         {
85                 RCUWriter<Ports> writer (ports);
86                 boost::shared_ptr<Ports> ps = writer.get_copy ();
87                 ps->clear ();
88         }
89
90         /* clear dead wood list in RCU */
91
92         ports.flush ();
93
94         /* clear out pending port deletion list. we know this is safe because
95          * the auto connect thread in Session is already dead when this is
96          * done. It doesn't use shared_ptr<Port> anyway.
97          */
98
99         _port_deletions_pending.reset ();
100
101         _port_remove_in_progress = false;
102 }
103
104
105 string
106 PortManager::make_port_name_relative (const string& portname) const
107 {
108         if (!_backend) {
109                 return portname;
110         }
111
112         string::size_type colon = portname.find (':');
113
114         if (colon == string::npos) {
115                 return portname;
116         }
117
118         if (portname.substr (0, colon) == _backend->my_name()) {
119                 return portname.substr (colon+1);
120         }
121
122         return portname;
123 }
124
125 string
126 PortManager::make_port_name_non_relative (const string& portname) const
127 {
128         string str;
129
130         if (portname.find_first_of (':') != string::npos) {
131                 return portname;
132         }
133
134         str  = _backend->my_name();
135         str += ':';
136         str += portname;
137
138         return str;
139 }
140
141 std::string
142 PortManager::get_pretty_name_by_name(const std::string& portname) const
143 {
144         PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
145         if (ph) {
146                 std::string value;
147                 std::string type;
148                 if (0 == _backend->get_port_property (ph,
149                                         "http://jackaudio.org/metadata/pretty-name",
150                                         value, type))
151                 {
152                         return value;
153                 }
154         }
155         return "";
156 }
157
158 bool
159 PortManager::port_is_mine (const string& portname) const
160 {
161         if (!_backend) {
162                 return true;
163         }
164
165         string self = _backend->my_name();
166
167         if (portname.find_first_of (':') != string::npos) {
168                 if (portname.substr (0, self.length ()) != self) {
169                         return false;
170                 }
171         }
172
173         return true;
174 }
175
176 bool
177 PortManager::port_is_physical (const std::string& portname) const
178 {
179         if (!_backend) {
180                 return false;
181         }
182
183         PortEngine::PortHandle ph = _backend->get_port_by_name (portname);
184         if (!ph) {
185                 return false;
186         }
187
188         return _backend->port_is_physical (ph);
189 }
190
191 void
192 PortManager::filter_midi_ports (vector<string>& ports, MidiPortFlags include, MidiPortFlags exclude)
193 {
194         if (!include && !exclude) {
195                 return;
196         }
197
198         for (vector<string>::iterator si = ports.begin(); si != ports.end(); ) {
199
200                 PortManager::MidiPortInformation mpi = midi_port_information (*si);
201
202                 if (mpi.pretty_name.empty()) {
203                         /* no information !!! */
204                         ++si;
205                         continue;
206                 }
207
208                 if (include) {
209                         if ((mpi.properties & include) != include) {
210                                 /* properties do not include requested ones */
211                                 si = ports.erase (si);
212                                 continue;
213                         }
214                 }
215
216                 if (exclude) {
217                         if ((mpi.properties & exclude)) {
218                                 /* properties include ones to avoid */
219                                 si = ports.erase (si);
220                                 continue;
221                         }
222                 }
223
224                 ++si;
225         }
226 }
227
228 void
229 PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s, MidiPortFlags include, MidiPortFlags exclude)
230 {
231         if (!_backend) {
232                 s.clear ();
233                 return;
234         }
235         _backend->get_physical_outputs (type, s);
236         filter_midi_ports (s, include, exclude);
237 }
238
239 void
240 PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s, MidiPortFlags include, MidiPortFlags exclude)
241 {
242         if (!_backend) {
243                 s.clear ();
244                 return;
245         }
246
247         _backend->get_physical_inputs (type, s);
248         filter_midi_ports (s, include, exclude);
249 }
250
251 ChanCount
252 PortManager::n_physical_outputs () const
253 {
254         if (!_backend) {
255                 return ChanCount::ZERO;
256         }
257
258         return _backend->n_physical_outputs ();
259 }
260
261 ChanCount
262 PortManager::n_physical_inputs () const
263 {
264         if (!_backend) {
265                 return ChanCount::ZERO;
266         }
267         return _backend->n_physical_inputs ();
268 }
269
270 /** @param name Full or short name of port
271  *  @return Corresponding Port or 0.
272  */
273
274 boost::shared_ptr<Port>
275 PortManager::get_port_by_name (const string& portname)
276 {
277         if (!_backend) {
278                 return boost::shared_ptr<Port>();
279         }
280
281         if (!port_is_mine (portname)) {
282                 /* not an ardour port */
283                 return boost::shared_ptr<Port> ();
284         }
285
286         boost::shared_ptr<Ports> pr = ports.reader();
287         std::string rel = make_port_name_relative (portname);
288         Ports::iterator x = pr->find (rel);
289
290         if (x != pr->end()) {
291                 /* its possible that the port was renamed by some 3rd party and
292                    we don't know about it. check for this (the check is quick
293                    and cheap), and if so, rename the port (which will alter
294                    the port map as a side effect).
295                 */
296                 const std::string check = make_port_name_relative (_backend->get_port_name (x->second->port_handle()));
297                 if (check != rel) {
298                         x->second->set_name (check);
299                 }
300                 return x->second;
301         }
302
303         return boost::shared_ptr<Port> ();
304 }
305
306 void
307 PortManager::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
308 {
309         RCUWriter<Ports> writer (ports);
310         boost::shared_ptr<Ports> p = writer.get_copy();
311         Ports::iterator x = p->find (old_relative_name);
312
313         if (x != p->end()) {
314                 boost::shared_ptr<Port> port = x->second;
315                 p->erase (x);
316                 p->insert (make_pair (new_relative_name, port));
317         }
318 }
319
320 int
321 PortManager::get_ports (DataType type, PortList& pl)
322 {
323         boost::shared_ptr<Ports> plist = ports.reader();
324         for (Ports::iterator p = plist->begin(); p != plist->end(); ++p) {
325                 if (p->second->type() == type) {
326                         pl.push_back (p->second);
327                 }
328         }
329         return pl.size();
330 }
331
332 int
333 PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
334 {
335         s.clear();
336
337         if (!_backend) {
338                 return 0;
339         }
340
341         return _backend->get_ports (port_name_pattern, type, flags, s);
342 }
343
344 void
345 PortManager::port_registration_failure (const std::string& portname)
346 {
347         if (!_backend) {
348                 return;
349         }
350
351         string full_portname = _backend->my_name();
352         full_portname += ':';
353         full_portname += portname;
354
355
356         PortEngine::PortHandle p = _backend->get_port_by_name (full_portname);
357         string reason;
358
359         if (p) {
360                 reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
361         } else {
362                 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);
363         }
364
365         throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
366 }
367
368 struct PortDeleter
369 {
370         void operator() (Port* p) {
371                 AudioEngine::instance()->add_pending_port_deletion (p);
372         }
373 };
374
375 boost::shared_ptr<Port>
376 PortManager::register_port (DataType dtype, const string& portname, bool input, bool async, PortFlags flags)
377 {
378         boost::shared_ptr<Port> newport;
379
380         /* limit the possible flags that can be set */
381
382         flags = PortFlags (flags & (Hidden|Shadow|IsTerminal));
383
384         try {
385                 if (dtype == DataType::AUDIO) {
386                         DEBUG_TRACE (DEBUG::Ports, string_compose ("registering AUDIO port %1, input %2\n",
387                                                                    portname, input));
388                         newport.reset (new AudioPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)),
389                                        PortDeleter());
390                 } else if (dtype == DataType::MIDI) {
391                         if (async) {
392                                 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering ASYNC MIDI port %1, input %2\n",
393                                                                            portname, input));
394                                 newport.reset (new AsyncMIDIPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)),
395                                                PortDeleter());
396                         } else {
397                                 DEBUG_TRACE (DEBUG::Ports, string_compose ("registering MIDI port %1, input %2\n",
398                                                                            portname, input));
399                                 newport.reset (new MidiPort (portname, PortFlags ((input ? IsInput : IsOutput) | flags)),
400                                                PortDeleter());
401                         }
402                 } else {
403                         throw PortRegistrationFailure("unable to create port (unknown type)");
404                 }
405
406                 RCUWriter<Ports> writer (ports);
407                 boost::shared_ptr<Ports> ps = writer.get_copy ();
408                 ps->insert (make_pair (make_port_name_relative (portname), newport));
409
410                 /* writer goes out of scope, forces update */
411
412         }
413
414         catch (PortRegistrationFailure& err) {
415                 throw err;
416         } catch (std::exception& e) {
417                 throw PortRegistrationFailure(string_compose(
418                                 _("unable to create port: %1"), e.what()).c_str());
419         } catch (...) {
420                 throw PortRegistrationFailure("unable to create port (unknown error)");
421         }
422
423         DEBUG_TRACE (DEBUG::Ports, string_compose ("\t%2 port registration success, ports now = %1\n", ports.reader()->size(), this));
424         return newport;
425 }
426
427 boost::shared_ptr<Port>
428 PortManager::register_input_port (DataType type, const string& portname, bool async, PortFlags extra_flags)
429 {
430         return register_port (type, portname, true, async, extra_flags);
431 }
432
433 boost::shared_ptr<Port>
434 PortManager::register_output_port (DataType type, const string& portname, bool async, PortFlags extra_flags)
435 {
436         return register_port (type, portname, false, async, extra_flags);
437 }
438
439 int
440 PortManager::unregister_port (boost::shared_ptr<Port> port)
441 {
442         /* This is a little subtle. We do not call the backend's port
443          * unregistration code from here. That is left for the Port
444          * destructor. We are trying to drop references to the Port object
445          * here, so that its destructor will run and it will unregister itself.
446          */
447
448         /* caller must hold process lock */
449
450         {
451                 RCUWriter<Ports> writer (ports);
452                 boost::shared_ptr<Ports> ps = writer.get_copy ();
453                 Ports::iterator x = ps->find (make_port_name_relative (port->name()));
454
455                 if (x != ps->end()) {
456                         DEBUG_TRACE (DEBUG::Ports, string_compose ("removing %1 from port map (uc=%2)\n", port->name(), port.use_count()));
457                         ps->erase (x);
458                 }
459
460                 /* writer goes out of scope, forces update */
461         }
462
463         ports.flush ();
464
465         return 0;
466 }
467
468 bool
469 PortManager::connected (const string& port_name)
470 {
471         if (!_backend) {
472                 return false;
473         }
474
475         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
476
477         if (!handle) {
478                 return false;
479         }
480
481         return _backend->connected (handle);
482 }
483
484 bool
485 PortManager::physically_connected (const string& port_name)
486 {
487         if (!_backend) {
488                 return false;
489         }
490
491         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
492
493         if (!handle) {
494                 return false;
495         }
496
497         return _backend->physically_connected (handle);
498 }
499
500 int
501 PortManager::get_connections (const string& port_name, std::vector<std::string>& s)
502 {
503         if (!_backend) {
504                 s.clear ();
505                 return 0;
506         }
507
508         PortEngine::PortHandle handle = _backend->get_port_by_name (port_name);
509
510         if (!handle) {
511                 s.clear ();
512                 return 0;
513         }
514
515         return _backend->get_connections (handle, s);
516 }
517
518 int
519 PortManager::connect (const string& source, const string& destination)
520 {
521         int ret;
522
523         string s = make_port_name_non_relative (source);
524         string d = make_port_name_non_relative (destination);
525
526         boost::shared_ptr<Port> src = get_port_by_name (s);
527         boost::shared_ptr<Port> dst = get_port_by_name (d);
528
529         if (src) {
530                 ret = src->connect (d);
531         } else if (dst) {
532                 ret = dst->connect (s);
533         } else {
534                 /* neither port is known to us ...hand-off to the PortEngine
535                  */
536                 if (_backend) {
537                         ret = _backend->connect (s, d);
538                 } else {
539                         ret = -1;
540                 }
541         }
542
543         if (ret > 0) {
544                 /* already exists - no error, no warning */
545         } else if (ret < 0) {
546                 error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
547                                         source, s, destination, d)
548                       << endmsg;
549         }
550
551         return ret;
552 }
553
554 int
555 PortManager::disconnect (const string& source, const string& destination)
556 {
557         int ret;
558
559         string s = make_port_name_non_relative (source);
560         string d = make_port_name_non_relative (destination);
561
562         boost::shared_ptr<Port> src = get_port_by_name (s);
563         boost::shared_ptr<Port> dst = get_port_by_name (d);
564
565         if (src) {
566                 ret = src->disconnect (d);
567         } else if (dst) {
568                 ret = dst->disconnect (s);
569         } else {
570                 /* neither port is known to us ...hand-off to the PortEngine
571                  */
572                 if (_backend) {
573                         ret = _backend->disconnect (s, d);
574                 } else {
575                         ret = -1;
576                 }
577         }
578         return ret;
579 }
580
581 int
582 PortManager::disconnect (boost::shared_ptr<Port> port)
583 {
584         return port->disconnect_all ();
585 }
586
587 int
588 PortManager::disconnect (std::string const & name)
589 {
590         PortEngine::PortHandle ph = _backend->get_port_by_name (name);
591         if (ph) {
592                 return _backend->disconnect_all (ph);
593         }
594         return -2;
595 }
596
597 int
598 PortManager::reestablish_ports ()
599 {
600         Ports::iterator i;
601
602         boost::shared_ptr<Ports> p = ports.reader ();
603
604         DEBUG_TRACE (DEBUG::Ports, string_compose ("reestablish %1 ports\n", p->size()));
605
606         for (i = p->begin(); i != p->end(); ++i) {
607                 if (i->second->reestablish ()) {
608                         error << string_compose (_("Re-establising port %1 failed"), i->second->name()) << endmsg;
609                         std::cerr << string_compose (_("Re-establising port %1 failed"), i->second->name()) << std::endl;
610                         break;
611                 }
612         }
613
614         if (i != p->end()) {
615                 /* failed */
616                 remove_all_ports ();
617                 return -1;
618         }
619
620         return 0;
621 }
622
623 int
624 PortManager::reconnect_ports ()
625 {
626         boost::shared_ptr<Ports> p = ports.reader ();
627
628         if (!Profile->get_trx()) {
629                 /* re-establish connections */
630
631                 DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
632
633                 for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
634                         i->second->reconnect ();
635                 }
636         }
637
638         return 0;
639 }
640
641 void
642 PortManager::connect_callback (const string& a, const string& b, bool conn)
643 {
644         boost::shared_ptr<Port> port_a;
645         boost::shared_ptr<Port> port_b;
646         Ports::iterator x;
647         boost::shared_ptr<Ports> pr = ports.reader ();
648
649         x = pr->find (make_port_name_relative (a));
650         if (x != pr->end()) {
651                 port_a = x->second;
652         }
653
654         x = pr->find (make_port_name_relative (b));
655         if (x != pr->end()) {
656                 port_b = x->second;
657         }
658
659         PortConnectedOrDisconnected (
660                 port_a, a,
661                 port_b, b,
662                 conn
663                 ); /* EMIT SIGNAL */
664 }
665
666 void
667 PortManager::registration_callback ()
668 {
669         if (!_port_remove_in_progress) {
670
671                 {
672                         Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
673                         midi_info_dirty = true;
674                 }
675
676                 PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
677         }
678 }
679
680 bool
681 PortManager::can_request_input_monitoring () const
682 {
683         if (!_backend) {
684                 return false;
685         }
686
687         return _backend->can_monitor_input ();
688 }
689
690 void
691 PortManager::request_input_monitoring (const string& name, bool yn) const
692 {
693         if (!_backend) {
694                 return;
695         }
696
697         PortEngine::PortHandle ph = _backend->get_port_by_name (name);
698
699         if (ph) {
700                 _backend->request_input_monitoring (ph, yn);
701         }
702 }
703
704 void
705 PortManager::ensure_input_monitoring (const string& name, bool yn) const
706 {
707         if (!_backend) {
708                 return;
709         }
710
711         PortEngine::PortHandle ph = _backend->get_port_by_name (name);
712
713         if (ph) {
714                 _backend->ensure_input_monitoring (ph, yn);
715         }
716 }
717
718 uint32_t
719 PortManager::port_name_size() const
720 {
721         if (!_backend) {
722                 return 0;
723         }
724
725         return _backend->port_name_size ();
726 }
727
728 string
729 PortManager::my_name() const
730 {
731         if (!_backend) {
732                 return string();
733         }
734
735         return _backend->my_name();
736 }
737
738 int
739 PortManager::graph_order_callback ()
740 {
741         if (!_port_remove_in_progress) {
742                 GraphReordered(); /* EMIT SIGNAL */
743         }
744
745         return 0;
746 }
747
748 void
749 PortManager::cycle_start (pframes_t nframes)
750 {
751         Port::set_global_port_buffer_offset (0);
752         Port::set_cycle_framecnt (nframes);
753
754         _cycle_ports = ports.reader ();
755
756         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
757                 p->second->cycle_start (nframes);
758         }
759 }
760
761 void
762 PortManager::cycle_end (pframes_t nframes)
763 {
764         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
765                 p->second->cycle_end (nframes);
766         }
767
768         for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
769                 p->second->flush_buffers (nframes);
770         }
771
772         _cycle_ports.reset ();
773
774         /* we are done */
775 }
776
777 void
778 PortManager::silence (pframes_t nframes, Session *s)
779 {
780         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
781                 if (s && i->second == s->mtc_output_port ()) {
782                         continue;
783                 }
784                 if (s && i->second == s->midi_clock_output_port ()) {
785                         continue;
786                 }
787                 if (s && i->second == s->ltc_output_port ()) {
788                         continue;
789                 }
790                 if (boost::dynamic_pointer_cast<AsyncMIDIPort>(i->second)) {
791                         continue;
792                 }
793                 if (i->second->sends_output()) {
794                         i->second->get_buffer(nframes).silence(nframes);
795                 }
796         }
797 }
798
799 void
800 PortManager::silence_outputs (pframes_t nframes)
801 {
802         std::vector<std::string> port_names;
803         if (get_ports("", DataType::AUDIO, IsOutput, port_names)) {
804                 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
805                         if (!port_is_mine(*p)) {
806                                 continue;
807                         }
808                         PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
809                         if (!ph) {
810                                 continue;
811                         }
812                         void *buf = _backend->get_buffer(ph, nframes);
813                         if (!buf) {
814                                 continue;
815                         }
816                         memset (buf, 0, sizeof(float) * nframes);
817                 }
818         }
819
820         if (get_ports("", DataType::MIDI, IsOutput, port_names)) {
821                 for (std::vector<std::string>::iterator p = port_names.begin(); p != port_names.end(); ++p) {
822                         if (!port_is_mine(*p)) {
823                                 continue;
824                         }
825                         PortEngine::PortHandle ph = _backend->get_port_by_name (*p);
826                         if (!ph) {
827                                 continue;
828                         }
829                         void *buf = _backend->get_buffer(ph, nframes);
830                         if (!buf) {
831                                 continue;
832                         }
833                         _backend->midi_clear (buf);
834                 }
835         }
836 }
837
838 void
839 PortManager::check_monitoring ()
840 {
841         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
842
843                 bool x;
844
845                 if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
846                         i->second->set_last_monitor (x);
847                         /* XXX I think this is dangerous, due to
848                            a likely mutex in the signal handlers ...
849                         */
850                         i->second->MonitorInputChanged (x); /* EMIT SIGNAL */
851                 }
852         }
853 }
854
855 void
856 PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
857 {
858         for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
859
860                 if (i->second->sends_output()) {
861
862                         boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
863                         if (ap) {
864                                 Sample* s = ap->engine_get_whole_audio_buffer ();
865                                 gain_t g = base_gain;
866
867                                 for (pframes_t n = 0; n < nframes; ++n) {
868                                         *s++ *= g;
869                                         g -= gain_step;
870                                 }
871                         }
872                 }
873         }
874 }
875
876 PortEngine&
877 PortManager::port_engine()
878 {
879         assert (_backend);
880         return *_backend;
881 }
882
883 bool
884 PortManager::port_is_control_only (std::string const& name)
885 {
886         static regex_t compiled_pattern;
887         static string pattern;
888
889         if (pattern.empty()) {
890
891                 /* This is a list of regular expressions that match ports
892                  * related to physical MIDI devices that we do not want to
893                  * expose as normal physical ports.
894                  */
895
896                 const char * const control_only_ports[] = {
897                         X_(".*Ableton Push.*"),
898                         X_(".*FaderPort .*"),
899                 };
900
901                 pattern = "(";
902                 for (size_t n = 0; n < sizeof (control_only_ports)/sizeof (control_only_ports[0]); ++n) {
903                         if (n > 0) {
904                                 pattern += '|';
905                         }
906                         pattern += control_only_ports[n];
907                 }
908                 pattern += ')';
909
910                 regcomp (&compiled_pattern, pattern.c_str(), REG_EXTENDED|REG_NOSUB);
911         }
912
913         return regexec (&compiled_pattern, name.c_str(), 0, 0, 0) == 0;
914 }
915
916 PortManager::MidiPortInformation
917 PortManager::midi_port_information (std::string const & name)
918 {
919         Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
920
921         fill_midi_port_info_locked ();
922
923         MidiPortInfo::iterator x = midi_port_info.find (name);
924
925         if (x != midi_port_info.end()) {
926                 return x->second;
927         }
928
929         return MidiPortInformation ();
930 }
931
932 void
933 PortManager::get_known_midi_ports (vector<string>& copy)
934 {
935         Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
936
937         fill_midi_port_info_locked ();
938
939         for (MidiPortInfo::const_iterator x = midi_port_info.begin(); x != midi_port_info.end(); ++x) {
940                 copy.push_back (x->first);
941         }
942 }
943
944 void
945 PortManager::get_midi_selection_ports (vector<string>& copy)
946 {
947         Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
948
949         fill_midi_port_info_locked ();
950
951         for (MidiPortInfo::const_iterator x = midi_port_info.begin(); x != midi_port_info.end(); ++x) {
952                 if (x->second.properties & MidiPortSelection) {
953                         copy.push_back (x->first);
954                 }
955         }
956 }
957
958 void
959 PortManager::set_midi_port_pretty_name (string const & port, string const & pretty)
960 {
961         {
962                 Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
963
964                 fill_midi_port_info_locked ();
965
966                 MidiPortInfo::iterator x = midi_port_info.find (port);
967                 if (x == midi_port_info.end()) {
968                         return;
969                 }
970                 x->second.pretty_name = pretty;
971         }
972
973         /* push into back end */
974
975         PortEngine::PortHandle ph = _backend->get_port_by_name (port);
976
977         if (ph) {
978                 _backend->set_port_property (ph, "http://jackaudio.org/metadata/pretty-name", pretty, string());
979         }
980
981         MidiPortInfoChanged (); /* EMIT SIGNAL*/
982 }
983
984 void
985 PortManager::add_midi_port_flags (string const & port, MidiPortFlags flags)
986 {
987         bool emit = false;
988
989         {
990                 Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
991
992                 fill_midi_port_info_locked ();
993
994                 MidiPortInfo::iterator x = midi_port_info.find (port);
995                 if (x != midi_port_info.end()) {
996                         if ((x->second.properties & flags) != flags) { // at least one missing
997                                 x->second.properties = MidiPortFlags (x->second.properties | flags);
998                                 emit = true;
999                         }
1000                 }
1001         }
1002
1003         if (emit) {
1004                 if (flags & MidiPortSelection) {
1005                         MidiSelectionPortsChanged (); /* EMIT SIGNAL */
1006                 }
1007
1008                 if (flags != MidiPortSelection) {
1009                         MidiPortInfoChanged (); /* EMIT SIGNAL */
1010                 }
1011
1012                 save_midi_port_info ();
1013         }
1014 }
1015
1016 void
1017 PortManager::remove_midi_port_flags (string const & port, MidiPortFlags flags)
1018 {
1019         bool emit = false;
1020
1021         {
1022                 Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
1023
1024                 fill_midi_port_info_locked ();
1025
1026                 MidiPortInfo::iterator x = midi_port_info.find (port);
1027                 if (x != midi_port_info.end()) {
1028                         if (x->second.properties & flags) { // at least one is set
1029                                 x->second.properties = MidiPortFlags (x->second.properties & ~flags);
1030                                 emit = true;
1031                         }
1032                 }
1033         }
1034
1035         if (emit) {
1036                 if (flags & MidiPortSelection) {
1037                         MidiSelectionPortsChanged (); /* EMIT SIGNAL */
1038                 }
1039
1040                 if (flags != MidiPortSelection) {
1041                         MidiPortInfoChanged (); /* EMIT SIGNAL */
1042                 }
1043
1044                 save_midi_port_info ();
1045         }
1046 }
1047
1048 string
1049 PortManager::midi_port_info_file ()
1050 {
1051         return Glib::build_filename (user_config_directory(), X_("midi_port_info"));
1052 }
1053
1054 void
1055 PortManager::save_midi_port_info ()
1056 {
1057         string path = midi_port_info_file ();
1058
1059         XMLNode* root = new XMLNode (X_("MidiPortInfo"));
1060
1061         {
1062                 Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
1063
1064                 if (midi_port_info.empty()) {
1065                         delete root;
1066                         return;
1067                 }
1068
1069                 for (MidiPortInfo::iterator i = midi_port_info.begin(); i != midi_port_info.end(); ++i) {
1070                         XMLNode* node = new XMLNode (X_("port"));
1071                         node->add_property (X_("name"), i->first);
1072                         node->add_property (X_("input"), i->second.input ? X_("yes") : X_("no"));
1073                         node->add_property (X_("properties"), enum_2_string (i->second.properties));
1074                         root->add_child_nocopy (*node);
1075                 }
1076         }
1077
1078         XMLTree tree;
1079
1080         tree.set_root (root);
1081
1082         if (!tree.write (path)) {
1083                 error << string_compose (_("Could not save MIDI port info to %1"), path) << endmsg;
1084         }
1085 }
1086
1087 void
1088 PortManager::load_midi_port_info ()
1089 {
1090         string path = midi_port_info_file ();
1091         XMLTree tree;
1092
1093         if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1094                 return;
1095         }
1096
1097         if (!tree.read (path)) {
1098                 error << string_compose (_("Cannot load MIDI port info from %1"), path) << endmsg;
1099                 return;
1100         }
1101
1102         midi_port_info.clear ();
1103
1104         for (XMLNodeConstIterator i = tree.root()->children().begin(); i != tree.root()->children().end(); ++i) {
1105                 XMLProperty const* prop;
1106                 MidiPortInformation mpi;
1107                 string name;
1108
1109                 if ((prop = (*i)->property (X_("name"))) == 0) {
1110                         continue;
1111                 }
1112
1113                 name = prop->value ();
1114
1115                 if ((prop = (*i)->property (X_("input"))) == 0) {
1116                         continue;
1117                 }
1118                 mpi.input = string_is_affirmative (prop->value());
1119
1120                 if ((prop = (*i)->property (X_("properties"))) == 0) {
1121                         continue;
1122                 }
1123
1124                 mpi.properties = (MidiPortFlags) string_2_enum (prop->value(), mpi.properties);
1125
1126                 midi_port_info.insert (make_pair (name, mpi));
1127         }
1128 }
1129
1130 void
1131 PortManager::fill_midi_port_info ()
1132 {
1133         Glib::Threads::Mutex::Lock lm (midi_port_info_mutex);
1134         fill_midi_port_info_locked ();
1135 }
1136
1137 void
1138 PortManager::fill_midi_port_info_locked ()
1139 {
1140         /* MIDI info mutex MUST be held */
1141
1142         if (!midi_info_dirty) {
1143                 return;
1144         }
1145
1146         std::vector<string> ports;
1147
1148         AudioEngine::instance()->get_ports (string(), DataType::MIDI, IsOutput, ports);
1149
1150         for (vector<string>::iterator p = ports.begin(); p != ports.end(); ++p) {
1151
1152                 if (port_is_mine (*p)) {
1153                         continue;
1154                 }
1155
1156                 if (midi_port_info.find (*p) == midi_port_info.end()) {
1157                         MidiPortInformation mpi;
1158                         mpi.pretty_name = *p;
1159                         mpi.input = true;
1160
1161                         if (port_is_control_only (*p)) {
1162                                 mpi.properties = MidiPortFlags (mpi.properties | MidiPortControl);
1163                         }
1164 #ifdef LINUX
1165                         if ((*p.find (X_("Midi Through")) != string::npos ||
1166                              (*p).find (X_("Midi-Through")) != string::npos))
1167                         {
1168                                 mpi.properties = MidiPortFlags (mpi.properties | MidiPortVirtual);
1169                         }
1170 #endif
1171                         midi_port_info.insert (make_pair (*p, mpi));
1172                 }
1173         }
1174
1175         AudioEngine::instance()->get_ports (string(), DataType::MIDI, IsInput, ports);
1176
1177         for (vector<string>::iterator p = ports.begin(); p != ports.end(); ++p) {
1178
1179                 if (port_is_mine (*p)) {
1180                         continue;
1181                 }
1182
1183                 if (midi_port_info.find (*p) == midi_port_info.end()) {
1184                         MidiPortInformation mpi;
1185                         mpi.pretty_name = *p;
1186                         mpi.input = false;
1187
1188                         if (port_is_control_only (*p)) {
1189                                 mpi.properties = MidiPortFlags (mpi.properties | MidiPortControl);
1190                         }
1191 #ifdef LINUX
1192                         if ((*p.find (X_("Midi Through")) != string::npos ||
1193                              (*p).find (X_("Midi-Through")) != string::npos))
1194                         {
1195                                 mpi.properties = MidiPortFlags (mpi.properties | MidiPortVirtual);
1196                         }
1197 #endif
1198                         midi_port_info.insert (make_pair (*p, mpi));
1199                 }
1200         }
1201
1202         /* now push/pull pretty name information between backend and the
1203          * PortManager
1204          */
1205
1206         for (MidiPortInfo::iterator x = midi_port_info.begin(); x != midi_port_info.end(); ++x) {
1207                 PortEngine::PortHandle ph = _backend->get_port_by_name (x->first);
1208
1209                 if (x->second.pretty_name != x->first) {
1210                         /* name set in port info ... propagate */
1211                         _backend->set_port_property (ph, "http://jackaudio.org/metadata/pretty-name", x->second.pretty_name, string());
1212                 } else {
1213                         /* check with backend for pre-existing pretty name */
1214                         if (ph) {
1215                                 string value;
1216                                 string type;
1217                                 if (0 == _backend->get_port_property (ph,
1218                                                                       "http://jackaudio.org/metadata/pretty-name",
1219                                                                       value, type)) {
1220                                         x->second.pretty_name = value;
1221                                 }
1222                         }
1223                 }
1224         }
1225
1226         midi_info_dirty = false;
1227 }