Support selecting separate input and output devices in portaudio backend
[ardour.git] / libs / backends / portaudio / portaudio_backend.cc
1 /*
2  * Copyright (C) 2015-2015 Robin Gareus <robin@gareus.org>
3  * Copyright (C) 2013 Paul Davis
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include <regex.h>
21
22 #ifndef PLATFORM_WINDOWS
23 #include <sys/mman.h>
24 #include <sys/time.h>
25 #endif
26
27 #include <glibmm.h>
28
29 #include "portaudio_backend.h"
30 #include "rt_thread.h"
31
32 #include "pbd/compose.h"
33 #include "pbd/error.h"
34 #include "pbd/file_utils.h"
35 #include "ardour/filesystem_paths.h"
36 #include "ardour/port_manager.h"
37 #include "i18n.h"
38
39 using namespace ARDOUR;
40
41 static std::string s_instance_name;
42 size_t PortAudioBackend::_max_buffer_size = 8192;
43 std::vector<std::string> PortAudioBackend::_midi_options;
44 std::vector<AudioBackend::DeviceStatus> PortAudioBackend::_input_audio_device_status;
45 std::vector<AudioBackend::DeviceStatus> PortAudioBackend::_output_audio_device_status;
46
47 PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info)
48         : AudioBackend (e, info)
49         , _pcmio (0)
50         , _run (false)
51         , _active (false)
52         , _freewheel (false)
53         , _measure_latency (false)
54         , _last_process_start (0)
55         , _input_audio_device("")
56         , _output_audio_device("")
57         , _midi_driver_option(_("None"))
58         , _samplerate (48000)
59         , _samples_per_period (1024)
60         , _n_inputs (0)
61         , _n_outputs (0)
62         , _systemic_audio_input_latency (0)
63         , _systemic_audio_output_latency (0)
64         , _dsp_load (0)
65         , _processed_samples (0)
66         , _port_change_flag (false)
67 {
68         _instance_name = s_instance_name;
69         pthread_mutex_init (&_port_callback_mutex, 0);
70
71         _pcmio = new PortAudioIO ();
72 }
73
74 PortAudioBackend::~PortAudioBackend ()
75 {
76         delete _pcmio; _pcmio = 0;
77         pthread_mutex_destroy (&_port_callback_mutex);
78 }
79
80 /* AUDIOBACKEND API */
81
82 std::string
83 PortAudioBackend::name () const
84 {
85         return X_("PortAudio");
86 }
87
88 bool
89 PortAudioBackend::is_realtime () const
90 {
91         return true;
92 }
93
94 bool
95 PortAudioBackend::requires_driver_selection() const
96 {
97         // we could do this but implementation would need changing
98         /*
99         if (enumerate_drivers().size() == 1) {
100                 return false;
101         }
102         */
103         return true;
104 }
105
106 std::vector<std::string>
107 PortAudioBackend::enumerate_drivers () const
108 {
109         std::vector<std::string> currently_available;
110         _pcmio->host_api_list (currently_available);
111         return currently_available;
112 }
113
114 int
115 PortAudioBackend::set_driver (const std::string& name)
116 {
117         _pcmio->set_host_api (name);
118         return 0;
119 }
120
121 bool
122 PortAudioBackend::use_separate_input_and_output_devices () const
123 {
124         return true;
125 }
126
127 std::vector<AudioBackend::DeviceStatus>
128 PortAudioBackend::enumerate_devices () const
129 {
130         return std::vector<AudioBackend::DeviceStatus>();
131 }
132
133 std::vector<AudioBackend::DeviceStatus>
134 PortAudioBackend::enumerate_input_devices () const
135 {
136         _pcmio->discover();
137         _input_audio_device_status.clear();
138         std::map<int, std::string> input_devices;
139         _pcmio->input_device_list(input_devices);
140
141         for (std::map<int, std::string>::const_iterator i = input_devices.begin (); i != input_devices.end(); ++i) {
142                 if (_input_audio_device == "") _input_audio_device = i->second;
143                 _input_audio_device_status.push_back (DeviceStatus (i->second, true));
144         }
145         return _input_audio_device_status;
146 }
147
148 std::vector<AudioBackend::DeviceStatus>
149 PortAudioBackend::enumerate_output_devices () const
150 {
151         _pcmio->discover();
152         _output_audio_device_status.clear();
153         std::map<int, std::string> output_devices;
154         _pcmio->output_device_list(output_devices);
155
156         for (std::map<int, std::string>::const_iterator i = output_devices.begin (); i != output_devices.end(); ++i) {
157                 if (_output_audio_device == "") _output_audio_device = i->second;
158                 _output_audio_device_status.push_back (DeviceStatus (i->second, true));
159         }
160         return _output_audio_device_status;
161 }
162
163 std::vector<float>
164 PortAudioBackend::available_sample_rates (const std::string&) const
165 {
166         std::vector<float> sr;
167         _pcmio->available_sample_rates(name_to_id(_input_audio_device), sr);
168         return sr;
169 }
170
171 std::vector<uint32_t>
172 PortAudioBackend::available_buffer_sizes (const std::string&) const
173 {
174         std::vector<uint32_t> bs;
175         _pcmio->available_buffer_sizes(name_to_id(_input_audio_device), bs);
176         return bs;
177 }
178
179 uint32_t
180 PortAudioBackend::available_input_channel_count (const std::string&) const
181 {
182         return 128; // TODO query current device
183 }
184
185 uint32_t
186 PortAudioBackend::available_output_channel_count (const std::string&) const
187 {
188         return 128; // TODO query current device
189 }
190
191 bool
192 PortAudioBackend::can_change_sample_rate_when_running () const
193 {
194         return false;
195 }
196
197 bool
198 PortAudioBackend::can_change_buffer_size_when_running () const
199 {
200         return false; // TODO
201 }
202
203 int
204 PortAudioBackend::set_device_name (const std::string& d)
205 {
206         return 0;
207 }
208
209 int
210 PortAudioBackend::set_input_device_name (const std::string& d)
211 {
212         _input_audio_device = d;
213         return 0;
214 }
215
216 int
217 PortAudioBackend::set_output_device_name (const std::string& d)
218 {
219         _output_audio_device = d;
220         return 0;
221 }
222
223 int
224 PortAudioBackend::set_sample_rate (float sr)
225 {
226         if (sr <= 0) { return -1; }
227         // TODO check if it's in the list of valid SR
228         _samplerate = sr;
229         engine.sample_rate_change (sr);
230         return 0;
231 }
232
233 int
234 PortAudioBackend::set_buffer_size (uint32_t bs)
235 {
236         if (bs <= 0 || bs >= _max_buffer_size) {
237                 return -1;
238         }
239         _samples_per_period = bs;
240         engine.buffer_size_change (bs);
241         return 0;
242 }
243
244 int
245 PortAudioBackend::set_interleaved (bool yn)
246 {
247         if (!yn) { return 0; }
248         return -1;
249 }
250
251 int
252 PortAudioBackend::set_input_channels (uint32_t cc)
253 {
254         _n_inputs = cc;
255         return 0;
256 }
257
258 int
259 PortAudioBackend::set_output_channels (uint32_t cc)
260 {
261         _n_outputs = cc;
262         return 0;
263 }
264
265 int
266 PortAudioBackend::set_systemic_input_latency (uint32_t sl)
267 {
268         _systemic_audio_input_latency = sl;
269         return 0;
270 }
271
272 int
273 PortAudioBackend::set_systemic_output_latency (uint32_t sl)
274 {
275         _systemic_audio_output_latency = sl;
276         return 0;
277 }
278
279 /* Retrieving parameters */
280 std::string
281 PortAudioBackend::device_name () const
282 {
283         return "Unused";
284 }
285
286 std::string
287 PortAudioBackend::input_device_name () const
288 {
289         return _input_audio_device;
290 }
291
292 std::string
293 PortAudioBackend::output_device_name () const
294 {
295         return _output_audio_device;
296 }
297
298 float
299 PortAudioBackend::sample_rate () const
300 {
301         return _samplerate;
302 }
303
304 uint32_t
305 PortAudioBackend::buffer_size () const
306 {
307         return _samples_per_period;
308 }
309
310 bool
311 PortAudioBackend::interleaved () const
312 {
313         return false;
314 }
315
316 uint32_t
317 PortAudioBackend::input_channels () const
318 {
319         return _n_inputs;
320 }
321
322 uint32_t
323 PortAudioBackend::output_channels () const
324 {
325         return _n_outputs;
326 }
327
328 uint32_t
329 PortAudioBackend::systemic_input_latency () const
330 {
331         return _systemic_audio_input_latency;
332 }
333
334 uint32_t
335 PortAudioBackend::systemic_output_latency () const
336 {
337         return _systemic_audio_output_latency;
338 }
339
340 /* MIDI */
341
342 std::vector<std::string>
343 PortAudioBackend::enumerate_midi_options () const
344 {
345         if (_midi_options.empty()) {
346                 //_midi_options.push_back (_("PortMidi"));
347                 _midi_options.push_back (_("None"));
348         }
349         return _midi_options;
350 }
351
352 int
353 PortAudioBackend::set_midi_option (const std::string& opt)
354 {
355         if (opt != _("None") /* && opt != _("PortMidi")*/) {
356                 return -1;
357         }
358         _midi_driver_option = opt;
359         return 0;
360 }
361
362 std::string
363 PortAudioBackend::midi_option () const
364 {
365         return _midi_driver_option;
366 }
367
368 /* State Control */
369
370 static void * pthread_process (void *arg)
371 {
372         PortAudioBackend *d = static_cast<PortAudioBackend *>(arg);
373         d->main_process_thread ();
374         pthread_exit (0);
375         return 0;
376 }
377
378 int
379 PortAudioBackend::_start (bool for_latency_measurement)
380 {
381         if (!_active && _run) {
382                 // recover from 'halted', reap threads
383                 stop();
384         }
385
386         if (_active || _run) {
387                 PBD::error << _("PortAudioBackend: already active.") << endmsg;
388                 return -1;
389         }
390
391         if (_ports.size()) {
392                 PBD::warning << _("PortAudioBackend: recovering from unclean shutdown, port registry is not empty.") << endmsg;
393                 _system_inputs.clear();
394                 _system_outputs.clear();
395                 _system_midi_in.clear();
396                 _system_midi_out.clear();
397                 _ports.clear();
398         }
399
400         /* reset internal state */
401         _dsp_load = 0;
402         _freewheeling = false;
403         _freewheel = false;
404         _last_process_start = 0;
405
406         _pcmio->pcm_setup (name_to_id(_input_audio_device), name_to_id(_output_audio_device), _samplerate, _samples_per_period);
407
408         switch (_pcmio->state ()) {
409                 case 0: /* OK */ break;
410                 case -1: PBD::error << _("PortAudioBackend: failed to open device.") << endmsg; break;
411                 default: PBD::error << _("PortAudioBackend: initialization failed.") << endmsg; break;
412         }
413         if (_pcmio->state ()) {
414                 return -1;
415         }
416
417         if (_n_outputs != _pcmio->n_playback_channels ()) {
418                 _n_outputs = _pcmio->n_playback_channels ();
419                 PBD::info << _("PortAudioBackend: adjusted output channel count to match device.") << endmsg;
420         }
421
422         if (_n_inputs != _pcmio->n_capture_channels ()) {
423                 _n_inputs = _pcmio->n_capture_channels ();
424                 PBD::info << _("PortAudioBackend: adjusted input channel count to match device.") << endmsg;
425         }
426 #if 0
427         if (_pcmio->samples_per_period() != _samples_per_period) {
428                 _samples_per_period = _pcmio->samples_per_period();
429                 PBD::warning << _("PortAudioBackend: samples per period does not match.") << endmsg;
430         }
431 #endif
432
433         if (_pcmio->sample_rate() != _samplerate) {
434                 _samplerate = _pcmio->sample_rate();
435                 engine.sample_rate_change (_samplerate);
436                 PBD::warning << _("PortAudioBackend: sample rate does not match.") << endmsg;
437         }
438
439         _measure_latency = for_latency_measurement;
440
441         _run = true;
442         _port_change_flag = false;
443
444         // TODO MIDI
445
446         if (register_system_audio_ports()) {
447                 PBD::error << _("PortAudioBackend: failed to register system ports.") << endmsg;
448                 _run = false;
449                 return -1;
450         }
451
452         engine.sample_rate_change (_samplerate);
453         engine.buffer_size_change (_samples_per_period);
454
455         if (engine.reestablish_ports ()) {
456                 PBD::error << _("PortAudioBackend: Could not re-establish ports.") << endmsg;
457                 _run = false;
458                 return -1;
459         }
460
461         engine.reconnect_ports ();
462         _run = true;
463         _port_change_flag = false;
464
465         if (_realtime_pthread_create (SCHED_FIFO, -20, 100000,
466                                 &_main_thread, pthread_process, this))
467         {
468                 if (pthread_create (&_main_thread, NULL, pthread_process, this))
469                 {
470                         PBD::error << _("PortAudioBackend: failed to create process thread.") << endmsg;
471                         _run = false;
472                         return -1;
473                 } else {
474                         PBD::warning << _("PortAudioBackend: cannot acquire realtime permissions.") << endmsg;
475                 }
476         }
477
478         int timeout = 5000;
479         while (!_active && --timeout > 0) { Glib::usleep (1000); }
480
481         if (timeout == 0 || !_active) {
482                 PBD::error << _("PortAudioBackend: failed to start.") << endmsg;
483                 _pcmio->pcm_stop();
484                 _run = false;
485                 unregister_ports();
486                 _active = false;
487                 return -1;
488         }
489
490         return 0;
491 }
492
493 int
494 PortAudioBackend::stop ()
495 {
496         void *status;
497         if (!_run) {
498                 return 0;
499         }
500
501         _run = false;
502         if (pthread_join (_main_thread, &status)) {
503                 PBD::error << _("PortAudioBackend: failed to terminate.") << endmsg;
504                 return -1;
505         }
506
507
508         unregister_ports();
509
510         return (_active == false) ? 0 : -1;
511 }
512
513 int
514 PortAudioBackend::freewheel (bool onoff)
515 {
516         if (onoff == _freewheeling) {
517                 return 0;
518         }
519         _freewheeling = onoff;
520         return 0;
521 }
522
523 float
524 PortAudioBackend::dsp_load () const
525 {
526         return 100.f * _dsp_load;
527 }
528
529 size_t
530 PortAudioBackend::raw_buffer_size (DataType t)
531 {
532         switch (t) {
533                 case DataType::AUDIO:
534                         return _samples_per_period * sizeof(Sample);
535                 case DataType::MIDI:
536                         return _max_buffer_size; // XXX not really limited
537         }
538         return 0;
539 }
540
541 /* Process time */
542 framepos_t
543 PortAudioBackend::sample_time ()
544 {
545         return _processed_samples;
546 }
547
548 framepos_t
549 PortAudioBackend::sample_time_at_cycle_start ()
550 {
551         return _processed_samples;
552 }
553
554 pframes_t
555 PortAudioBackend::samples_since_cycle_start ()
556 {
557         if (!_active || !_run || _freewheeling || _freewheel) {
558                 return 0;
559         }
560         if (_last_process_start == 0) {
561                 return 0;
562         }
563
564         const int64_t elapsed_time_us = g_get_monotonic_time() - _last_process_start;
565         return std::max((pframes_t)0, (pframes_t)rint(1e-6 * elapsed_time_us * _samplerate));
566 }
567
568 int
569 PortAudioBackend::name_to_id(std::string device_name) const {
570         uint32_t device_id = UINT32_MAX;
571         std::map<int, std::string> devices;
572         _pcmio->input_device_list(devices);
573         _pcmio->output_device_list(devices);
574
575         for (std::map<int, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
576                 if (i->second == device_name) {
577                         device_id = i->first;
578                         break;
579                 }
580         }
581         return device_id;
582 }
583
584 void *
585 PortAudioBackend::portaudio_process_thread (void *arg)
586 {
587         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
588         boost::function<void ()> f = td->f;
589         delete td;
590         f ();
591         return 0;
592 }
593
594 int
595 PortAudioBackend::create_process_thread (boost::function<void()> func)
596 {
597         pthread_t thread_id;
598         pthread_attr_t attr;
599         size_t stacksize = 100000;
600
601         ThreadData* td = new ThreadData (this, func, stacksize);
602
603         if (_realtime_pthread_create (SCHED_FIFO, -21, stacksize,
604                                 &thread_id, portaudio_process_thread, td)) {
605                 pthread_attr_init (&attr);
606                 pthread_attr_setstacksize (&attr, stacksize);
607                 if (pthread_create (&thread_id, &attr, portaudio_process_thread, td)) {
608                         PBD::error << _("AudioEngine: cannot create process thread.") << endmsg;
609                         pthread_attr_destroy (&attr);
610                         return -1;
611                 }
612                 pthread_attr_destroy (&attr);
613         }
614
615         _threads.push_back (thread_id);
616         return 0;
617 }
618
619 int
620 PortAudioBackend::join_process_threads ()
621 {
622         int rv = 0;
623
624         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
625         {
626                 void *status;
627                 if (pthread_join (*i, &status)) {
628                         PBD::error << _("AudioEngine: cannot terminate process thread.") << endmsg;
629                         rv -= 1;
630                 }
631         }
632         _threads.clear ();
633         return rv;
634 }
635
636 bool
637 PortAudioBackend::in_process_thread ()
638 {
639         if (pthread_equal (_main_thread, pthread_self()) != 0) {
640                 return true;
641         }
642
643         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
644         {
645                 if (pthread_equal (*i, pthread_self ()) != 0) {
646                         return true;
647                 }
648         }
649         return false;
650 }
651
652 uint32_t
653 PortAudioBackend::process_thread_count ()
654 {
655         return _threads.size ();
656 }
657
658 void
659 PortAudioBackend::update_latencies ()
660 {
661         // trigger latency callback in RT thread (locked graph)
662         port_connect_add_remove_callback();
663 }
664
665 /* PORTENGINE API */
666
667 void*
668 PortAudioBackend::private_handle () const
669 {
670         return NULL;
671 }
672
673 const std::string&
674 PortAudioBackend::my_name () const
675 {
676         return _instance_name;
677 }
678
679 bool
680 PortAudioBackend::available () const
681 {
682         return _run && _active;
683 }
684
685 uint32_t
686 PortAudioBackend::port_name_size () const
687 {
688         return 256;
689 }
690
691 int
692 PortAudioBackend::set_port_name (PortEngine::PortHandle port, const std::string& name)
693 {
694         if (!valid_port (port)) {
695                 PBD::error << _("PortAudioBackend::set_port_name: Invalid Port(s)") << endmsg;
696                 return -1;
697         }
698         return static_cast<PamPort*>(port)->set_name (_instance_name + ":" + name);
699 }
700
701 std::string
702 PortAudioBackend::get_port_name (PortEngine::PortHandle port) const
703 {
704         if (!valid_port (port)) {
705                 PBD::error << _("PortAudioBackend::get_port_name: Invalid Port(s)") << endmsg;
706                 return std::string ();
707         }
708         return static_cast<PamPort*>(port)->name ();
709 }
710
711 PortEngine::PortHandle
712 PortAudioBackend::get_port_by_name (const std::string& name) const
713 {
714         PortHandle port = (PortHandle) find_port (name);
715         return port;
716 }
717
718 int
719 PortAudioBackend::get_ports (
720                 const std::string& port_name_pattern,
721                 DataType type, PortFlags flags,
722                 std::vector<std::string>& port_names) const
723 {
724         int rv = 0;
725         regex_t port_regex;
726         bool use_regexp = false;
727         if (port_name_pattern.size () > 0) {
728                 if (!regcomp (&port_regex, port_name_pattern.c_str (), REG_EXTENDED|REG_NOSUB)) {
729                         use_regexp = true;
730                 }
731         }
732         for (size_t i = 0; i < _ports.size (); ++i) {
733                 PamPort* port = _ports[i];
734                 if ((port->type () == type) && flags == (port->flags () & flags)) {
735                         if (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) {
736                                 port_names.push_back (port->name ());
737                                 ++rv;
738                         }
739                 }
740         }
741         if (use_regexp) {
742                 regfree (&port_regex);
743         }
744         return rv;
745 }
746
747 DataType
748 PortAudioBackend::port_data_type (PortEngine::PortHandle port) const
749 {
750         if (!valid_port (port)) {
751                 return DataType::NIL;
752         }
753         return static_cast<PamPort*>(port)->type ();
754 }
755
756 PortEngine::PortHandle
757 PortAudioBackend::register_port (
758                 const std::string& name,
759                 ARDOUR::DataType type,
760                 ARDOUR::PortFlags flags)
761 {
762         if (name.size () == 0) { return 0; }
763         if (flags & IsPhysical) { return 0; }
764         return add_port (_instance_name + ":" + name, type, flags);
765 }
766
767 PortEngine::PortHandle
768 PortAudioBackend::add_port (
769                 const std::string& name,
770                 ARDOUR::DataType type,
771                 ARDOUR::PortFlags flags)
772 {
773         assert(name.size ());
774         if (find_port (name)) {
775                 PBD::error << _("PortAudioBackend::register_port: Port already exists:")
776                                 << " (" << name << ")" << endmsg;
777                 return 0;
778         }
779         PamPort* port = NULL;
780         switch (type) {
781                 case DataType::AUDIO:
782                         port = new PortAudioPort (*this, name, flags);
783                         break;
784                 case DataType::MIDI:
785                         port = new PortMidiPort (*this, name, flags);
786                         break;
787                 default:
788                         PBD::error << _("PortAudioBackend::register_port: Invalid Data Type.") << endmsg;
789                         return 0;
790         }
791
792         _ports.push_back (port);
793
794         return port;
795 }
796
797 void
798 PortAudioBackend::unregister_port (PortEngine::PortHandle port_handle)
799 {
800         if (!_run) {
801                 return;
802         }
803         PamPort* port = static_cast<PamPort*>(port_handle);
804         std::vector<PamPort*>::iterator i = std::find (_ports.begin (), _ports.end (), static_cast<PamPort*>(port_handle));
805         if (i == _ports.end ()) {
806                 PBD::error << _("PortAudioBackend::unregister_port: Failed to find port") << endmsg;
807                 return;
808         }
809         disconnect_all(port_handle);
810         _ports.erase (i);
811         delete port;
812 }
813
814 int
815 PortAudioBackend::register_system_audio_ports()
816 {
817         LatencyRange lr;
818
819         const uint32_t a_ins = _n_inputs;
820         const uint32_t a_out = _n_outputs;
821
822         // XXX PA reported stream latencies don't match measurements
823         const uint32_t portaudio_reported_input_latency =  _samples_per_period ; //  _pcmio->capture_latency();
824         const uint32_t portaudio_reported_output_latency = /* _samples_per_period + */ _pcmio->playback_latency();
825
826         /* audio ports */
827         lr.min = lr.max = portaudio_reported_input_latency + (_measure_latency ? 0 : _systemic_audio_input_latency);
828         for (uint32_t i = 0; i < a_ins; ++i) {
829                 char tmp[64];
830                 snprintf(tmp, sizeof(tmp), "system:capture_%d", i+1);
831                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
832                 if (!p) return -1;
833                 set_latency_range (p, false, lr);
834                 _system_inputs.push_back(static_cast<PortAudioPort*>(p));
835         }
836
837         lr.min = lr.max = portaudio_reported_output_latency + (_measure_latency ? 0 : _systemic_audio_output_latency);
838         for (uint32_t i = 0; i < a_out; ++i) {
839                 char tmp[64];
840                 snprintf(tmp, sizeof(tmp), "system:playback_%d", i+1);
841                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
842                 if (!p) return -1;
843                 set_latency_range (p, true, lr);
844                 _system_outputs.push_back(static_cast<PamPort*>(p));
845         }
846         return 0;
847 }
848
849 void
850 PortAudioBackend::unregister_ports (bool system_only)
851 {
852         size_t i = 0;
853         _system_inputs.clear();
854         _system_outputs.clear();
855         _system_midi_in.clear();
856         _system_midi_out.clear();
857         while (i <  _ports.size ()) {
858                 PamPort* port = _ports[i];
859                 if (! system_only || (port->is_physical () && port->is_terminal ())) {
860                         port->disconnect_all ();
861                         delete port;
862                         _ports.erase (_ports.begin() + i);
863                 } else {
864                         ++i;
865                 }
866         }
867 }
868
869 int
870 PortAudioBackend::connect (const std::string& src, const std::string& dst)
871 {
872         PamPort* src_port = find_port (src);
873         PamPort* dst_port = find_port (dst);
874
875         if (!src_port) {
876                 PBD::error << _("PortAudioBackend::connect: Invalid Source port:")
877                                 << " (" << src <<")" << endmsg;
878                 return -1;
879         }
880         if (!dst_port) {
881                 PBD::error << _("PortAudioBackend::connect: Invalid Destination port:")
882                         << " (" << dst <<")" << endmsg;
883                 return -1;
884         }
885         return src_port->connect (dst_port);
886 }
887
888 int
889 PortAudioBackend::disconnect (const std::string& src, const std::string& dst)
890 {
891         PamPort* src_port = find_port (src);
892         PamPort* dst_port = find_port (dst);
893
894         if (!src_port || !dst_port) {
895                 PBD::error << _("PortAudioBackend::disconnect: Invalid Port(s)") << endmsg;
896                 return -1;
897         }
898         return src_port->disconnect (dst_port);
899 }
900
901 int
902 PortAudioBackend::connect (PortEngine::PortHandle src, const std::string& dst)
903 {
904         PamPort* dst_port = find_port (dst);
905         if (!valid_port (src)) {
906                 PBD::error << _("PortAudioBackend::connect: Invalid Source Port Handle") << endmsg;
907                 return -1;
908         }
909         if (!dst_port) {
910                 PBD::error << _("PortAudioBackend::connect: Invalid Destination Port")
911                         << " (" << dst << ")" << endmsg;
912                 return -1;
913         }
914         return static_cast<PamPort*>(src)->connect (dst_port);
915 }
916
917 int
918 PortAudioBackend::disconnect (PortEngine::PortHandle src, const std::string& dst)
919 {
920         PamPort* dst_port = find_port (dst);
921         if (!valid_port (src) || !dst_port) {
922                 PBD::error << _("PortAudioBackend::disconnect: Invalid Port(s)") << endmsg;
923                 return -1;
924         }
925         return static_cast<PamPort*>(src)->disconnect (dst_port);
926 }
927
928 int
929 PortAudioBackend::disconnect_all (PortEngine::PortHandle port)
930 {
931         if (!valid_port (port)) {
932                 PBD::error << _("PortAudioBackend::disconnect_all: Invalid Port") << endmsg;
933                 return -1;
934         }
935         static_cast<PamPort*>(port)->disconnect_all ();
936         return 0;
937 }
938
939 bool
940 PortAudioBackend::connected (PortEngine::PortHandle port, bool /* process_callback_safe*/)
941 {
942         if (!valid_port (port)) {
943                 PBD::error << _("PortAudioBackend::disconnect_all: Invalid Port") << endmsg;
944                 return false;
945         }
946         return static_cast<PamPort*>(port)->is_connected ();
947 }
948
949 bool
950 PortAudioBackend::connected_to (PortEngine::PortHandle src, const std::string& dst, bool /*process_callback_safe*/)
951 {
952         PamPort* dst_port = find_port (dst);
953         if (!valid_port (src) || !dst_port) {
954                 PBD::error << _("PortAudioBackend::connected_to: Invalid Port") << endmsg;
955                 return false;
956         }
957         return static_cast<PamPort*>(src)->is_connected (dst_port);
958 }
959
960 bool
961 PortAudioBackend::physically_connected (PortEngine::PortHandle port, bool /*process_callback_safe*/)
962 {
963         if (!valid_port (port)) {
964                 PBD::error << _("PortAudioBackend::physically_connected: Invalid Port") << endmsg;
965                 return false;
966         }
967         return static_cast<PamPort*>(port)->is_physically_connected ();
968 }
969
970 int
971 PortAudioBackend::get_connections (PortEngine::PortHandle port, std::vector<std::string>& names, bool /*process_callback_safe*/)
972 {
973         if (!valid_port (port)) {
974                 PBD::error << _("PortAudioBackend::get_connections: Invalid Port") << endmsg;
975                 return -1;
976         }
977
978         assert (0 == names.size ());
979
980         const std::vector<PamPort*>& connected_ports = static_cast<PamPort*>(port)->get_connections ();
981
982         for (std::vector<PamPort*>::const_iterator i = connected_ports.begin (); i != connected_ports.end (); ++i) {
983                 names.push_back ((*i)->name ());
984         }
985
986         return (int)names.size ();
987 }
988
989 /* MIDI */
990 int
991 PortAudioBackend::midi_event_get (
992                 pframes_t& timestamp,
993                 size_t& size, uint8_t** buf, void* port_buffer,
994                 uint32_t event_index)
995 {
996         if (!buf || !port_buffer) return -1;
997         PortMidiBuffer& source = * static_cast<PortMidiBuffer*>(port_buffer);
998         if (event_index >= source.size ()) {
999                 return -1;
1000         }
1001         PortMidiEvent * const event = source[event_index].get ();
1002
1003         timestamp = event->timestamp ();
1004         size = event->size ();
1005         *buf = event->data ();
1006         return 0;
1007 }
1008
1009 int
1010 PortAudioBackend::midi_event_put (
1011                 void* port_buffer,
1012                 pframes_t timestamp,
1013                 const uint8_t* buffer, size_t size)
1014 {
1015         if (!buffer || !port_buffer) return -1;
1016         PortMidiBuffer& dst = * static_cast<PortMidiBuffer*>(port_buffer);
1017         if (dst.size () && (pframes_t)dst.back ()->timestamp () > timestamp) {
1018 #ifndef NDEBUG
1019                 // nevermind, ::get_buffer() sorts events
1020                 fprintf (stderr, "PortMidiBuffer: unordered event: %d > %d\n",
1021                                 (pframes_t)dst.back ()->timestamp (), timestamp);
1022 #endif
1023         }
1024         dst.push_back (boost::shared_ptr<PortMidiEvent>(new PortMidiEvent (timestamp, buffer, size)));
1025         return 0;
1026 }
1027
1028 uint32_t
1029 PortAudioBackend::get_midi_event_count (void* port_buffer)
1030 {
1031         if (!port_buffer) return 0;
1032         return static_cast<PortMidiBuffer*>(port_buffer)->size ();
1033 }
1034
1035 void
1036 PortAudioBackend::midi_clear (void* port_buffer)
1037 {
1038         if (!port_buffer) return;
1039         PortMidiBuffer * buf = static_cast<PortMidiBuffer*>(port_buffer);
1040         assert (buf);
1041         buf->clear ();
1042 }
1043
1044 /* Monitoring */
1045
1046 bool
1047 PortAudioBackend::can_monitor_input () const
1048 {
1049         return false;
1050 }
1051
1052 int
1053 PortAudioBackend::request_input_monitoring (PortEngine::PortHandle, bool)
1054 {
1055         return -1;
1056 }
1057
1058 int
1059 PortAudioBackend::ensure_input_monitoring (PortEngine::PortHandle, bool)
1060 {
1061         return -1;
1062 }
1063
1064 bool
1065 PortAudioBackend::monitoring_input (PortEngine::PortHandle)
1066 {
1067         return false;
1068 }
1069
1070 /* Latency management */
1071
1072 void
1073 PortAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range)
1074 {
1075         if (!valid_port (port)) {
1076                 PBD::error << _("PamPort::set_latency_range (): invalid port.") << endmsg;
1077         }
1078         static_cast<PamPort*>(port)->set_latency_range (latency_range, for_playback);
1079 }
1080
1081 LatencyRange
1082 PortAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback)
1083 {
1084         LatencyRange r;
1085         if (!valid_port (port)) {
1086                 PBD::error << _("PamPort::get_latency_range (): invalid port.") << endmsg;
1087                 r.min = 0;
1088                 r.max = 0;
1089                 return r;
1090         }
1091         PamPort* p = static_cast<PamPort*>(port);
1092         assert(p);
1093
1094         r = p->latency_range (for_playback);
1095         // TODO MIDI
1096         if (p->is_physical() && p->is_terminal() && p->type() == DataType::AUDIO) {
1097                 if (p->is_input() && for_playback) {
1098                         r.min += _samples_per_period;
1099                         r.max += _samples_per_period;
1100                 }
1101                 if (p->is_output() && !for_playback) {
1102                         r.min += _samples_per_period;
1103                         r.max += _samples_per_period;
1104                 }
1105         }
1106         return r;
1107 }
1108
1109 /* Discovering physical ports */
1110
1111 bool
1112 PortAudioBackend::port_is_physical (PortEngine::PortHandle port) const
1113 {
1114         if (!valid_port (port)) {
1115                 PBD::error << _("PamPort::port_is_physical (): invalid port.") << endmsg;
1116                 return false;
1117         }
1118         return static_cast<PamPort*>(port)->is_physical ();
1119 }
1120
1121 void
1122 PortAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>& port_names)
1123 {
1124         for (size_t i = 0; i < _ports.size (); ++i) {
1125                 PamPort* port = _ports[i];
1126                 if ((port->type () == type) && port->is_input () && port->is_physical ()) {
1127                         port_names.push_back (port->name ());
1128                 }
1129         }
1130 }
1131
1132 void
1133 PortAudioBackend::get_physical_inputs (DataType type, std::vector<std::string>& port_names)
1134 {
1135         for (size_t i = 0; i < _ports.size (); ++i) {
1136                 PamPort* port = _ports[i];
1137                 if ((port->type () == type) && port->is_output () && port->is_physical ()) {
1138                         port_names.push_back (port->name ());
1139                 }
1140         }
1141 }
1142
1143 ChanCount
1144 PortAudioBackend::n_physical_outputs () const
1145 {
1146         int n_midi = 0;
1147         int n_audio = 0;
1148         for (size_t i = 0; i < _ports.size (); ++i) {
1149                 PamPort* port = _ports[i];
1150                 if (port->is_output () && port->is_physical ()) {
1151                         switch (port->type ()) {
1152                                 case DataType::AUDIO: ++n_audio; break;
1153                                 case DataType::MIDI: ++n_midi; break;
1154                                 default: break;
1155                         }
1156                 }
1157         }
1158         ChanCount cc;
1159         cc.set (DataType::AUDIO, n_audio);
1160         cc.set (DataType::MIDI, n_midi);
1161         return cc;
1162 }
1163
1164 ChanCount
1165 PortAudioBackend::n_physical_inputs () const
1166 {
1167         int n_midi = 0;
1168         int n_audio = 0;
1169         for (size_t i = 0; i < _ports.size (); ++i) {
1170                 PamPort* port = _ports[i];
1171                 if (port->is_input () && port->is_physical ()) {
1172                         switch (port->type ()) {
1173                                 case DataType::AUDIO: ++n_audio; break;
1174                                 case DataType::MIDI: ++n_midi; break;
1175                                 default: break;
1176                         }
1177                 }
1178         }
1179         ChanCount cc;
1180         cc.set (DataType::AUDIO, n_audio);
1181         cc.set (DataType::MIDI, n_midi);
1182         return cc;
1183 }
1184
1185 /* Getting access to the data buffer for a port */
1186
1187 void*
1188 PortAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes)
1189 {
1190         if (!port || !valid_port (port)) return NULL;
1191         return static_cast<PamPort*>(port)->get_buffer (nframes);
1192 }
1193
1194
1195 void *
1196 PortAudioBackend::main_process_thread ()
1197 {
1198         AudioEngine::thread_init_callback (this);
1199         _active = true;
1200         _processed_samples = 0;
1201
1202         uint64_t clock1, clock2;
1203         const int64_t nomial_time = 1e6 * _samples_per_period / _samplerate;
1204
1205         manager.registration_callback();
1206         manager.graph_order_callback();
1207
1208         if (_pcmio->pcm_start()) {
1209                 _pcmio->pcm_stop ();
1210                 _active = false;
1211                 engine.halted_callback("PortAudio I/O error.");
1212         }
1213
1214         while (_run) {
1215
1216                 if (_freewheeling != _freewheel) {
1217                         _freewheel = _freewheeling;
1218                         engine.freewheel_callback (_freewheel);
1219                 }
1220
1221                 if (!_freewheel) {
1222
1223                         switch (_pcmio->next_cycle (_samples_per_period)) {
1224                                 case 0: // OK
1225                                         break;
1226                                 case 1:
1227 #ifndef NDEBUG
1228                                         printf("PortAudio: Xrun\n");
1229 #endif
1230                                         engine.Xrun ();
1231                                         break;
1232                                 default:
1233                                         PBD::error << _("PortAudioBackend: I/O error. Audio Process Terminated.") << endmsg;
1234                                         break;
1235                         }
1236
1237                         uint32_t i = 0;
1238                         clock1 = g_get_monotonic_time();
1239
1240                         /* get audio */
1241                         i = 0;
1242                         for (std::vector<PamPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++i) {
1243                                 _pcmio->get_capture_channel (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period);
1244                         }
1245
1246                         /* de-queue incoming midi*/
1247                         i=0;
1248                         for (std::vector<PamPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
1249                                 PortMidiBuffer* mbuf = static_cast<PortMidiBuffer*>((*it)->get_buffer(0));
1250                                 mbuf->clear();
1251                         }
1252
1253                         /* clear output buffers */
1254                         for (std::vector<PamPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
1255                                 memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
1256                         }
1257
1258                         /* call engine process callback */
1259                         _last_process_start = g_get_monotonic_time();
1260                         if (engine.process_callback (_samples_per_period)) {
1261                                 _pcmio->pcm_stop ();
1262                                 _active = false;
1263                                 return 0;
1264                         }
1265 #if 0
1266                         /* mixdown midi */
1267                         for (std::vector<PamPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
1268                                 static_cast<PortBackendMidiPort*>(*it)->next_period();
1269                         }
1270
1271                         /* queue outgoing midi */
1272                         i = 0;
1273                         for (std::vector<PamPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
1274                                 // TODO
1275                         }
1276 #endif
1277
1278                         /* write back audio */
1279                         i = 0;
1280                         for (std::vector<PamPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it, ++i) {
1281                                 _pcmio->set_playback_channel (i, (float const*)(*it)->get_buffer (_samples_per_period), _samples_per_period);
1282                         }
1283
1284                         _processed_samples += _samples_per_period;
1285
1286                         /* calculate DSP load */
1287                         clock2 = g_get_monotonic_time();
1288                         const int64_t elapsed_time = clock2 - clock1;
1289                         _dsp_load = elapsed_time / (float) nomial_time;
1290
1291                 } else {
1292                         // Freewheelin'
1293
1294                         // zero audio input buffers
1295                         for (std::vector<PamPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
1296                                 memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
1297                         }
1298
1299                         clock1 = g_get_monotonic_time();
1300
1301                         // TODO clear midi or stop midi recv when entering fwheelin'
1302
1303                         _last_process_start = 0;
1304                         if (engine.process_callback (_samples_per_period)) {
1305                                 _pcmio->pcm_stop ();
1306                                 _active = false;
1307                                 return 0;
1308                         }
1309
1310                         // drop all outgoing MIDI messages
1311                         for (std::vector<PamPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
1312                                         void *bptr = (*it)->get_buffer(0);
1313                                         midi_clear(bptr);
1314                         }
1315
1316                         _dsp_load = 1.0;
1317                         Glib::usleep (100); // don't hog cpu
1318                 }
1319
1320                 bool connections_changed = false;
1321                 bool ports_changed = false;
1322                 if (!pthread_mutex_trylock (&_port_callback_mutex)) {
1323                         if (_port_change_flag) {
1324                                 ports_changed = true;
1325                                 _port_change_flag = false;
1326                         }
1327                         if (!_port_connection_queue.empty ()) {
1328                                 connections_changed = true;
1329                         }
1330                         while (!_port_connection_queue.empty ()) {
1331                                 PortConnectData *c = _port_connection_queue.back ();
1332                                 manager.connect_callback (c->a, c->b, c->c);
1333                                 _port_connection_queue.pop_back ();
1334                                 delete c;
1335                         }
1336                         pthread_mutex_unlock (&_port_callback_mutex);
1337                 }
1338                 if (ports_changed) {
1339                         manager.registration_callback();
1340                 }
1341                 if (connections_changed) {
1342                         manager.graph_order_callback();
1343                 }
1344                 if (connections_changed || ports_changed) {
1345                         engine.latency_callback(false);
1346                         engine.latency_callback(true);
1347                 }
1348
1349         }
1350         _pcmio->pcm_stop ();
1351         _active = false;
1352         if (_run) {
1353                 engine.halted_callback("PortAudio I/O error.");
1354         }
1355         return 0;
1356 }
1357
1358
1359 /******************************************************************************/
1360
1361 static boost::shared_ptr<PortAudioBackend> _instance;
1362
1363 static boost::shared_ptr<AudioBackend> backend_factory (AudioEngine& e);
1364 static int instantiate (const std::string& arg1, const std::string& /* arg2 */);
1365 static int deinstantiate ();
1366 static bool already_configured ();
1367 static bool available ();
1368
1369 static ARDOUR::AudioBackendInfo _descriptor = {
1370         "PortAudio",
1371         instantiate,
1372         deinstantiate,
1373         backend_factory,
1374         already_configured,
1375         available
1376 };
1377
1378 static boost::shared_ptr<AudioBackend>
1379 backend_factory (AudioEngine& e)
1380 {
1381         if (!_instance) {
1382                 _instance.reset (new PortAudioBackend (e, _descriptor));
1383         }
1384         return _instance;
1385 }
1386
1387 static int
1388 instantiate (const std::string& arg1, const std::string& /* arg2 */)
1389 {
1390         s_instance_name = arg1;
1391         return 0;
1392 }
1393
1394 static int
1395 deinstantiate ()
1396 {
1397         _instance.reset ();
1398         return 0;
1399 }
1400
1401 static bool
1402 already_configured ()
1403 {
1404         return false;
1405 }
1406
1407 static bool
1408 available ()
1409 {
1410         return true;
1411 }
1412
1413 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
1414 {
1415         return &_descriptor;
1416 }
1417
1418
1419 /******************************************************************************/
1420 PamPort::PamPort (PortAudioBackend &b, const std::string& name, PortFlags flags)
1421         : _osx_backend (b)
1422         , _name  (name)
1423         , _flags (flags)
1424 {
1425         _capture_latency_range.min = 0;
1426         _capture_latency_range.max = 0;
1427         _playback_latency_range.min = 0;
1428         _playback_latency_range.max = 0;
1429 }
1430
1431 PamPort::~PamPort () {
1432         disconnect_all ();
1433 }
1434
1435
1436 int PamPort::connect (PamPort *port)
1437 {
1438         if (!port) {
1439                 PBD::error << _("PamPort::connect (): invalid (null) port") << endmsg;
1440                 return -1;
1441         }
1442
1443         if (type () != port->type ()) {
1444                 PBD::error << _("PamPort::connect (): wrong port-type") << endmsg;
1445                 return -1;
1446         }
1447
1448         if (is_output () && port->is_output ()) {
1449                 PBD::error << _("PamPort::connect (): cannot inter-connect output ports.") << endmsg;
1450                 return -1;
1451         }
1452
1453         if (is_input () && port->is_input ()) {
1454                 PBD::error << _("PamPort::connect (): cannot inter-connect input ports.") << endmsg;
1455                 return -1;
1456         }
1457
1458         if (this == port) {
1459                 PBD::error << _("PamPort::connect (): cannot self-connect ports.") << endmsg;
1460                 return -1;
1461         }
1462
1463         if (is_connected (port)) {
1464 #if 0 // don't bother to warn about this for now. just ignore it
1465                 PBD::error << _("PamPort::connect (): ports are already connected:")
1466                         << " (" << name () << ") -> (" << port->name () << ")"
1467                         << endmsg;
1468 #endif
1469                 return -1;
1470         }
1471
1472         _connect (port, true);
1473         return 0;
1474 }
1475
1476
1477 void PamPort::_connect (PamPort *port, bool callback)
1478 {
1479         _connections.push_back (port);
1480         if (callback) {
1481                 port->_connect (this, false);
1482                 _osx_backend.port_connect_callback (name(),  port->name(), true);
1483         }
1484 }
1485
1486 int PamPort::disconnect (PamPort *port)
1487 {
1488         if (!port) {
1489                 PBD::error << _("PamPort::disconnect (): invalid (null) port") << endmsg;
1490                 return -1;
1491         }
1492
1493         if (!is_connected (port)) {
1494                 PBD::error << _("PamPort::disconnect (): ports are not connected:")
1495                         << " (" << name () << ") -> (" << port->name () << ")"
1496                         << endmsg;
1497                 return -1;
1498         }
1499         _disconnect (port, true);
1500         return 0;
1501 }
1502
1503 void PamPort::_disconnect (PamPort *port, bool callback)
1504 {
1505         std::vector<PamPort*>::iterator it = std::find (_connections.begin (), _connections.end (), port);
1506
1507         assert (it != _connections.end ());
1508
1509         _connections.erase (it);
1510
1511         if (callback) {
1512                 port->_disconnect (this, false);
1513                 _osx_backend.port_connect_callback (name(),  port->name(), false);
1514         }
1515 }
1516
1517
1518 void PamPort::disconnect_all ()
1519 {
1520         while (!_connections.empty ()) {
1521                 _connections.back ()->_disconnect (this, false);
1522                 _osx_backend.port_connect_callback (name(),  _connections.back ()->name(), false);
1523                 _connections.pop_back ();
1524         }
1525 }
1526
1527 bool
1528 PamPort::is_connected (const PamPort *port) const
1529 {
1530         return std::find (_connections.begin (), _connections.end (), port) != _connections.end ();
1531 }
1532
1533 bool PamPort::is_physically_connected () const
1534 {
1535         for (std::vector<PamPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
1536                 if ((*it)->is_physical ()) {
1537                         return true;
1538                 }
1539         }
1540         return false;
1541 }
1542
1543 /******************************************************************************/
1544
1545 PortAudioPort::PortAudioPort (PortAudioBackend &b, const std::string& name, PortFlags flags)
1546         : PamPort (b, name, flags)
1547 {
1548         memset (_buffer, 0, sizeof (_buffer));
1549 #ifndef PLATFORM_WINDOWS
1550         mlock(_buffer, sizeof (_buffer));
1551 #endif
1552 }
1553
1554 PortAudioPort::~PortAudioPort () { }
1555
1556 void* PortAudioPort::get_buffer (pframes_t n_samples)
1557 {
1558         if (is_input ()) {
1559                 std::vector<PamPort*>::const_iterator it = get_connections ().begin ();
1560                 if (it == get_connections ().end ()) {
1561                         memset (_buffer, 0, n_samples * sizeof (Sample));
1562                 } else {
1563                         PortAudioPort const * source = static_cast<const PortAudioPort*>(*it);
1564                         assert (source && source->is_output ());
1565                         memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
1566                         while (++it != get_connections ().end ()) {
1567                                 source = static_cast<const PortAudioPort*>(*it);
1568                                 assert (source && source->is_output ());
1569                                 Sample* dst = buffer ();
1570                                 const Sample* src = source->const_buffer ();
1571                                 for (uint32_t s = 0; s < n_samples; ++s, ++dst, ++src) {
1572                                         *dst += *src;
1573                                 }
1574                         }
1575                 }
1576         }
1577         return _buffer;
1578 }
1579
1580
1581 PortMidiPort::PortMidiPort (PortAudioBackend &b, const std::string& name, PortFlags flags)
1582         : PamPort (b, name, flags)
1583         , _n_periods (1)
1584         , _bufperiod (0)
1585 {
1586         _buffer[0].clear ();
1587         _buffer[1].clear ();
1588 }
1589
1590 PortMidiPort::~PortMidiPort () { }
1591
1592 struct MidiEventSorter {
1593         bool operator() (const boost::shared_ptr<PortMidiEvent>& a, const boost::shared_ptr<PortMidiEvent>& b) {
1594                 return *a < *b;
1595         }
1596 };
1597
1598 void* PortMidiPort::get_buffer (pframes_t /* nframes */)
1599 {
1600         if (is_input ()) {
1601                 (_buffer[_bufperiod]).clear ();
1602                 for (std::vector<PamPort*>::const_iterator i = get_connections ().begin ();
1603                                 i != get_connections ().end ();
1604                                 ++i) {
1605                         const PortMidiBuffer * src = static_cast<const PortMidiPort*>(*i)->const_buffer ();
1606                         for (PortMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
1607                                 (_buffer[_bufperiod]).push_back (boost::shared_ptr<PortMidiEvent>(new PortMidiEvent (**it)));
1608                         }
1609                 }
1610                 std::sort ((_buffer[_bufperiod]).begin (), (_buffer[_bufperiod]).end (), MidiEventSorter());
1611         }
1612         return &(_buffer[_bufperiod]);
1613 }
1614
1615 PortMidiEvent::PortMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size)
1616         : _size (size)
1617         , _timestamp (timestamp)
1618         , _data (0)
1619 {
1620         if (size > 0) {
1621                 _data = (uint8_t*) malloc (size);
1622                 memcpy (_data, data, size);
1623         }
1624 }
1625
1626 PortMidiEvent::PortMidiEvent (const PortMidiEvent& other)
1627         : _size (other.size ())
1628         , _timestamp (other.timestamp ())
1629         , _data (0)
1630 {
1631         if (other.size () && other.const_data ()) {
1632                 _data = (uint8_t*) malloc (other.size ());
1633                 memcpy (_data, other.const_data (), other.size ());
1634         }
1635 };
1636
1637 PortMidiEvent::~PortMidiEvent () {
1638         free (_data);
1639 };