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