Rename blocking thread function 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 #ifdef COMPILER_MINGW
28 #include <sys/time.h>
29 #endif
30
31 #include <glibmm.h>
32
33 #include "portaudio_backend.h"
34 #include "rt_thread.h"
35
36 #include "pbd/compose.h"
37 #include "pbd/error.h"
38 #include "pbd/file_utils.h"
39 #include "pbd/windows_timer_utils.h"
40 #include "pbd/windows_mmcss.h"
41
42 #include "ardour/filesystem_paths.h"
43 #include "ardour/port_manager.h"
44 #include "i18n.h"
45
46 #include "audio_utils.h"
47
48 #include "debug.h"
49
50 using namespace ARDOUR;
51
52 namespace {
53
54 const char * const winmme_driver_name = X_("WinMME");
55
56 }
57
58 static std::string s_instance_name;
59 size_t PortAudioBackend::_max_buffer_size = 8192;
60 std::vector<std::string> PortAudioBackend::_midi_options;
61 std::vector<AudioBackend::DeviceStatus> PortAudioBackend::_input_audio_device_status;
62 std::vector<AudioBackend::DeviceStatus> PortAudioBackend::_output_audio_device_status;
63
64 PortAudioBackend::PortAudioBackend (AudioEngine& e, AudioBackendInfo& info)
65         : AudioBackend (e, info)
66         , _pcmio (0)
67         , _run (false)
68         , _active (false)
69         , _freewheel (false)
70         , _freewheeling (false)
71         , _freewheel_ack (false)
72         , _reinit_thread_callback (false)
73         , _measure_latency (false)
74         , m_cycle_count(0)
75         , m_total_deviation_us(0)
76         , m_max_deviation_us(0)
77         , _input_audio_device("")
78         , _output_audio_device("")
79         , _midi_driver_option(get_standard_device_name(DeviceNone))
80         , _samplerate (48000)
81         , _samples_per_period (1024)
82         , _n_inputs (0)
83         , _n_outputs (0)
84         , _systemic_audio_input_latency (0)
85         , _systemic_audio_output_latency (0)
86         , _dsp_load (0)
87         , _processed_samples (0)
88         , _port_change_flag (false)
89 {
90         _instance_name = s_instance_name;
91         pthread_mutex_init (&_port_callback_mutex, 0);
92         pthread_mutex_init (&m_freewheel_mutex, 0);
93         pthread_cond_init (&m_freewheel_signal, 0);
94
95         _pcmio = new PortAudioIO ();
96         _midiio = new WinMMEMidiIO ();
97 }
98
99 PortAudioBackend::~PortAudioBackend ()
100 {
101         delete _pcmio; _pcmio = 0;
102         delete _midiio; _midiio = 0;
103
104         pthread_mutex_destroy (&_port_callback_mutex);
105         pthread_mutex_destroy (&m_freewheel_mutex);
106         pthread_cond_destroy (&m_freewheel_signal);
107 }
108
109 /* AUDIOBACKEND API */
110
111 std::string
112 PortAudioBackend::name () const
113 {
114         return X_("PortAudio");
115 }
116
117 bool
118 PortAudioBackend::is_realtime () const
119 {
120         return true;
121 }
122
123 bool
124 PortAudioBackend::requires_driver_selection() const
125 {
126         // we could do this but implementation would need changing
127         /*
128         if (enumerate_drivers().size() == 1) {
129                 return false;
130         }
131         */
132         return true;
133 }
134
135 std::vector<std::string>
136 PortAudioBackend::enumerate_drivers () const
137 {
138         DEBUG_AUDIO ("Portaudio: enumerate_drivers\n");
139         std::vector<std::string> currently_available;
140         _pcmio->host_api_list (currently_available);
141         return currently_available;
142 }
143
144 int
145 PortAudioBackend::set_driver (const std::string& name)
146 {
147         DEBUG_AUDIO (string_compose ("Portaudio: set_driver %1 \n", name));
148         if (!_pcmio->set_host_api (name)) {
149                 DEBUG_AUDIO (string_compose ("Portaudio: Unable to set_driver %1 \n", name));
150                 return -1;
151         }
152         _pcmio->update_devices();
153         return 0;
154 }
155
156 bool
157 PortAudioBackend::update_devices ()
158 {
159         return _pcmio->update_devices();
160 }
161
162 std::string
163 PortAudioBackend::driver_name () const
164 {
165         std::string driver_name = _pcmio->get_host_api ();
166         DEBUG_AUDIO (string_compose ("Portaudio: driver_name %1 \n", driver_name));
167         return driver_name;
168 }
169
170 bool
171 PortAudioBackend::use_separate_input_and_output_devices () const
172 {
173         return true;
174 }
175
176 std::vector<AudioBackend::DeviceStatus>
177 PortAudioBackend::enumerate_devices () const
178 {
179         DEBUG_AUDIO ("Portaudio: ERROR enumerate devices should not be called \n");
180         return std::vector<AudioBackend::DeviceStatus>();
181 }
182
183 std::vector<AudioBackend::DeviceStatus>
184 PortAudioBackend::enumerate_input_devices () const
185 {
186         _input_audio_device_status.clear();
187         std::map<int, std::string> input_devices;
188         _pcmio->input_device_list(input_devices);
189
190         for (std::map<int, std::string>::const_iterator i = input_devices.begin (); i != input_devices.end(); ++i) {
191                 if (_input_audio_device == "") _input_audio_device = i->second;
192                 _input_audio_device_status.push_back (DeviceStatus (i->second, true));
193         }
194         return _input_audio_device_status;
195 }
196
197 std::vector<AudioBackend::DeviceStatus>
198 PortAudioBackend::enumerate_output_devices () const
199 {
200         _output_audio_device_status.clear();
201         std::map<int, std::string> output_devices;
202         _pcmio->output_device_list(output_devices);
203
204         for (std::map<int, std::string>::const_iterator i = output_devices.begin (); i != output_devices.end(); ++i) {
205                 if (_output_audio_device == "") _output_audio_device = i->second;
206                 _output_audio_device_status.push_back (DeviceStatus (i->second, true));
207         }
208         return _output_audio_device_status;
209 }
210
211 std::vector<float>
212 PortAudioBackend::available_sample_rates (const std::string&) const
213 {
214         DEBUG_AUDIO ("Portaudio: available_sample_rates\n");
215         std::vector<float> sr;
216         _pcmio->available_sample_rates(name_to_id(_input_audio_device), sr);
217         return sr;
218 }
219
220 std::vector<uint32_t>
221 PortAudioBackend::available_buffer_sizes (const std::string&) const
222 {
223         DEBUG_AUDIO ("Portaudio: available_buffer_sizes\n");
224         std::vector<uint32_t> bs;
225         _pcmio->available_buffer_sizes(name_to_id(_input_audio_device), bs);
226         return bs;
227 }
228
229 uint32_t
230 PortAudioBackend::available_input_channel_count (const std::string&) const
231 {
232         return 128; // TODO query current device
233 }
234
235 uint32_t
236 PortAudioBackend::available_output_channel_count (const std::string&) const
237 {
238         return 128; // TODO query current device
239 }
240
241 bool
242 PortAudioBackend::can_change_sample_rate_when_running () const
243 {
244         return false;
245 }
246
247 bool
248 PortAudioBackend::can_change_buffer_size_when_running () const
249 {
250         return false; // TODO
251 }
252
253 int
254 PortAudioBackend::set_device_name (const std::string& d)
255 {
256         DEBUG_AUDIO ("Portaudio: set_device_name should not be called\n");
257         return 0;
258 }
259
260 int
261 PortAudioBackend::set_input_device_name (const std::string& d)
262 {
263         DEBUG_AUDIO (string_compose ("Portaudio: set_input_device_name %1\n", d));
264         _input_audio_device = d;
265         return 0;
266 }
267
268 int
269 PortAudioBackend::set_output_device_name (const std::string& d)
270 {
271         DEBUG_AUDIO (string_compose ("Portaudio: set_output_device_name %1\n", d));
272         _output_audio_device = d;
273         return 0;
274 }
275
276 int
277 PortAudioBackend::set_sample_rate (float sr)
278 {
279         if (sr <= 0) { return -1; }
280         // TODO check if it's in the list of valid SR
281         _samplerate = sr;
282         engine.sample_rate_change (sr);
283         return 0;
284 }
285
286 int
287 PortAudioBackend::set_buffer_size (uint32_t bs)
288 {
289         if (bs <= 0 || bs >= _max_buffer_size) {
290                 return -1;
291         }
292         _samples_per_period = bs;
293         engine.buffer_size_change (bs);
294         return 0;
295 }
296
297 int
298 PortAudioBackend::set_interleaved (bool yn)
299 {
300         if (!yn) { return 0; }
301         return -1;
302 }
303
304 int
305 PortAudioBackend::set_input_channels (uint32_t cc)
306 {
307         _n_inputs = cc;
308         return 0;
309 }
310
311 int
312 PortAudioBackend::set_output_channels (uint32_t cc)
313 {
314         _n_outputs = cc;
315         return 0;
316 }
317
318 int
319 PortAudioBackend::set_systemic_input_latency (uint32_t sl)
320 {
321         _systemic_audio_input_latency = sl;
322         return 0;
323 }
324
325 int
326 PortAudioBackend::set_systemic_output_latency (uint32_t sl)
327 {
328         _systemic_audio_output_latency = sl;
329         return 0;
330 }
331
332 /* Retrieving parameters */
333 std::string
334 PortAudioBackend::device_name () const
335 {
336         return "Unused";
337 }
338
339 std::string
340 PortAudioBackend::input_device_name () const
341 {
342         return _input_audio_device;
343 }
344
345 std::string
346 PortAudioBackend::output_device_name () const
347 {
348         return _output_audio_device;
349 }
350
351 float
352 PortAudioBackend::sample_rate () const
353 {
354         return _samplerate;
355 }
356
357 uint32_t
358 PortAudioBackend::buffer_size () const
359 {
360         return _samples_per_period;
361 }
362
363 bool
364 PortAudioBackend::interleaved () const
365 {
366         return false;
367 }
368
369 uint32_t
370 PortAudioBackend::input_channels () const
371 {
372         return _n_inputs;
373 }
374
375 uint32_t
376 PortAudioBackend::output_channels () const
377 {
378         return _n_outputs;
379 }
380
381 uint32_t
382 PortAudioBackend::systemic_input_latency () const
383 {
384         return _systemic_audio_input_latency;
385 }
386
387 uint32_t
388 PortAudioBackend::systemic_output_latency () const
389 {
390         return _systemic_audio_output_latency;
391 }
392
393 std::string
394 PortAudioBackend::control_app_name () const
395 {
396         return _pcmio->control_app_name (name_to_id (_input_audio_device));
397 }
398
399 void
400 PortAudioBackend::launch_control_app ()
401 {
402         return _pcmio->launch_control_app (name_to_id(_input_audio_device));
403 }
404
405 /* MIDI */
406
407 std::vector<std::string>
408 PortAudioBackend::enumerate_midi_options () const
409 {
410         if (_midi_options.empty()) {
411                 _midi_options.push_back (winmme_driver_name);
412                 _midi_options.push_back (get_standard_device_name(DeviceNone));
413         }
414         return _midi_options;
415 }
416
417 int
418 PortAudioBackend::set_midi_option (const std::string& opt)
419 {
420         if (opt != get_standard_device_name(DeviceNone) && opt != winmme_driver_name) {
421                 return -1;
422         }
423         DEBUG_MIDI (string_compose ("Setting midi option to %1\n", opt));
424         _midi_driver_option = opt;
425         return 0;
426 }
427
428 std::string
429 PortAudioBackend::midi_option () const
430 {
431         return _midi_driver_option;
432 }
433
434 /* State Control */
435
436 static void * blocking_thread_func (void *arg)
437 {
438         PortAudioBackend *d = static_cast<PortAudioBackend *>(arg);
439         d->main_blocking_process_thread ();
440         pthread_exit (0);
441         return 0;
442 }
443
444 bool
445 PortAudioBackend::engine_halted ()
446 {
447         return !_active && _run;
448 }
449
450 bool
451 PortAudioBackend::running ()
452 {
453         return _active || _run;
454 }
455
456 int
457 PortAudioBackend::_start (bool for_latency_measurement)
458 {
459         if (engine_halted()) {
460                 stop();
461         }
462
463         if (running()) {
464                 DEBUG_AUDIO("Already started.\n");
465                 return BackendReinitializationError;
466         }
467
468         if (_ports.size()) {
469                 DEBUG_AUDIO(
470                     "Recovering from unclean shutdown, port registry is not empty.\n");
471                 _system_inputs.clear();
472                 _system_outputs.clear();
473                 _system_midi_in.clear();
474                 _system_midi_out.clear();
475                 _ports.clear();
476         }
477
478         /* reset internal state */
479         _dsp_load = 0;
480         _freewheeling = false;
481         _freewheel = false;
482
483         PaErrorCode err = paNoError;
484
485 #ifdef USE_BLOCKING_API
486         err = _pcmio->open_blocking_stream(name_to_id(_input_audio_device),
487                                            name_to_id(_output_audio_device),
488                                            _samplerate,
489                                            _samples_per_period);
490
491 #else
492         err = _pcmio->open_callback_stream(name_to_id(_input_audio_device),
493                                            name_to_id(_output_audio_device),
494                                            _samplerate,
495                                            _samples_per_period,
496                                            portaudio_callback,
497                                            this);
498
499 #endif
500
501         // reintepret Portaudio error messages
502         switch (err) {
503         case paNoError:
504                 break;
505         case paBadIODeviceCombination:
506                 return DeviceConfigurationNotSupportedError;
507         case paInvalidChannelCount:
508                 return ChannelCountNotSupportedError;
509         case paInvalidSampleRate:
510                 return SampleRateNotSupportedError;
511         default:
512                 return AudioDeviceOpenError;
513         }
514
515         if (_n_outputs != _pcmio->n_playback_channels ()) {
516                 _n_outputs = _pcmio->n_playback_channels ();
517                 PBD::info << get_error_string(OutputChannelCountNotSupportedError) << endmsg;
518         }
519
520         if (_n_inputs != _pcmio->n_capture_channels ()) {
521                 _n_inputs = _pcmio->n_capture_channels ();
522                 PBD::info << get_error_string(InputChannelCountNotSupportedError) << endmsg;
523         }
524 #if 0
525         if (_pcmio->samples_per_period() != _samples_per_period) {
526                 _samples_per_period = _pcmio->samples_per_period();
527                 PBD::warning << _("PortAudioBackend: samples per period does not match.") << endmsg;
528         }
529 #endif
530
531         if (_pcmio->sample_rate() != _samplerate) {
532                 _samplerate = _pcmio->sample_rate();
533                 engine.sample_rate_change (_samplerate);
534                 PBD::warning << get_error_string(SampleRateNotSupportedError) << endmsg;
535         }
536
537         _measure_latency = for_latency_measurement;
538
539         _run = true;
540         _port_change_flag = false;
541
542         if (_midi_driver_option == winmme_driver_name) {
543                 _midiio->set_enabled(true);
544                 //_midiio->set_port_changed_callback(midi_port_change, this);
545                 _midiio->start(); // triggers port discovery, callback coremidi_rediscover()
546         }
547
548         m_cycle_timer.set_samplerate(_samplerate);
549         m_cycle_timer.set_samples_per_cycle(_samples_per_period);
550
551         m_dsp_calc.set_max_time_us (m_cycle_timer.get_length_us());
552
553         DEBUG_MIDI ("Registering MIDI ports\n");
554
555         if (register_system_midi_ports () != 0) {
556                 DEBUG_PORTS("Failed to register system midi ports.\n")
557                 _run = false;
558                 return PortRegistrationError;
559         }
560
561         DEBUG_AUDIO ("Registering Audio ports\n");
562
563         if (register_system_audio_ports()) {
564                 DEBUG_PORTS("Failed to register system audio ports.\n");
565                 _run = false;
566                 return PortRegistrationError;
567         }
568
569         engine.sample_rate_change (_samplerate);
570         engine.buffer_size_change (_samples_per_period);
571
572         if (engine.reestablish_ports ()) {
573                 DEBUG_PORTS("Could not re-establish ports.\n");
574                 _run = false;
575                 return PortReconnectError;
576         }
577
578         engine.reconnect_ports ();
579         _run = true;
580         _port_change_flag = false;
581
582 #ifdef USE_BLOCKING_API
583         if (!start_blocking_process_thread()) {
584                 return ProcessThreadStartError;
585         }
586 #else
587         if (_pcmio->start_stream() != paNoError) {
588                 DEBUG_AUDIO("Unable to start stream\n");
589                 return AudioDeviceOpenError;
590         }
591
592         if (!start_freewheel_process_thread()) {
593                 DEBUG_AUDIO("Unable to start freewheel thread\n");
594                 stop();
595                 return ProcessThreadStartError;
596         }
597 #endif
598
599         return NoError;
600 }
601
602 int
603 PortAudioBackend::portaudio_callback(const void* input,
604                                      void* output,
605                                      unsigned long frame_count,
606                                      const PaStreamCallbackTimeInfo* time_info,
607                                      PaStreamCallbackFlags status_flags,
608                                      void* user_data)
609 {
610         PortAudioBackend* pa_backend = static_cast<PortAudioBackend*>(user_data);
611
612         if (!pa_backend->process_callback((const float*)input,
613                                           (float*)output,
614                                           frame_count,
615                                           time_info,
616                                           status_flags)) {
617                 return paAbort;
618         }
619         return paContinue;
620 }
621
622 bool
623 PortAudioBackend::process_callback(const float* input,
624                                    float* output,
625                                    uint32_t frame_count,
626                                    const PaStreamCallbackTimeInfo* timeInfo,
627                                    PaStreamCallbackFlags statusFlags)
628 {
629         _active = true;
630
631         m_dsp_calc.set_start_timestamp_us (PBD::get_microseconds());
632
633         if (_run && _freewheel && !_freewheel_ack) {
634                 // acknowledge freewheeling; hand-over thread ID
635                 pthread_mutex_lock (&m_freewheel_mutex);
636                 if (_freewheel) {
637                         DEBUG_AUDIO("Setting _freewheel_ack = true;\n");
638                         _freewheel_ack = true;
639                 }
640                 DEBUG_AUDIO("Signalling freewheel thread\n");
641                 pthread_cond_signal (&m_freewheel_signal);
642                 pthread_mutex_unlock (&m_freewheel_mutex);
643         }
644
645         if (statusFlags & paInputUnderflow ||
646                 statusFlags & paInputOverflow ||
647                 statusFlags & paOutputUnderflow ||
648                 statusFlags & paOutputOverflow ) {
649                 DEBUG_AUDIO("PortAudio: Xrun\n");
650                 engine.Xrun();
651                 return true;
652         }
653
654         if (!_run || _freewheel) {
655                 memset(output, 0, frame_count * sizeof(float) * _system_outputs.size());
656                 return true;
657         }
658
659         bool in_main_thread = pthread_equal(m_main_thread, pthread_self());
660
661         if (_reinit_thread_callback || !in_main_thread) {
662                 _reinit_thread_callback = false;
663                 m_main_thread = pthread_self();
664                 AudioEngine::thread_init_callback (this);
665         }
666
667         return blocking_process_main (input, output);
668 }
669
670 bool
671 PortAudioBackend::start_blocking_process_thread ()
672 {
673         if (_realtime_pthread_create (SCHED_FIFO, -20, 100000,
674                                 &_main_blocking_thread, blocking_thread_func, this))
675         {
676                 if (pthread_create (&_main_blocking_thread, NULL, blocking_thread_func, this))
677                 {
678                         DEBUG_AUDIO("Failed to create main audio thread\n");
679                         _run = false;
680                         return false;
681                 } else {
682                         PBD::warning << get_error_string(AquireRealtimePermissionError) << endmsg;
683                 }
684         }
685
686         int timeout = 5000;
687         while (!_active && --timeout > 0) { Glib::usleep (1000); }
688
689         if (timeout == 0 || !_active) {
690                 DEBUG_AUDIO("Failed to start main audio thread\n");
691                 _pcmio->close_stream();
692                 _run = false;
693                 unregister_ports();
694                 _active = false;
695                 return false;
696         }
697         return true;
698 }
699
700 bool
701 PortAudioBackend::stop_blocking_process_thread ()
702 {
703         void *status;
704
705         if (pthread_join (_main_blocking_thread, &status)) {
706                 DEBUG_AUDIO("Failed to stop main audio thread\n");
707                 return false;
708         }
709
710         return true;
711 }
712
713 int
714 PortAudioBackend::stop ()
715 {
716         if (!_run) {
717                 return 0;
718         }
719
720         _midiio->stop();
721
722         _run = false;
723
724 #ifdef USE_BLOCKING_API
725         if (!stop_blocking_process_thread ()) {
726                 return -1;
727         }
728 #else
729         _pcmio->close_stream ();
730         _active = false;
731
732         if (!stop_freewheel_process_thread ()) {
733                 return -1;
734         }
735
736 #endif
737
738         unregister_ports();
739
740         return (_active == false) ? 0 : -1;
741 }
742
743 static void* freewheel_thread(void* arg)
744 {
745         PortAudioBackend* d = static_cast<PortAudioBackend*>(arg);
746         d->freewheel_process_thread ();
747         pthread_exit (0);
748         return 0;
749 }
750
751 bool
752 PortAudioBackend::start_freewheel_process_thread ()
753 {
754         if (pthread_create(&m_pthread_freewheel, NULL, freewheel_thread, this)) {
755                 DEBUG_AUDIO("Failed to create main audio thread\n");
756                 return false;
757         }
758
759         int timeout = 5000;
760         while (!m_freewheel_thread_active && --timeout > 0) { Glib::usleep (1000); }
761
762         if (timeout == 0 || !m_freewheel_thread_active) {
763                 DEBUG_AUDIO("Failed to start freewheel thread\n");
764                 return false;
765         }
766         return true;
767 }
768
769 bool
770 PortAudioBackend::stop_freewheel_process_thread ()
771 {
772         void *status;
773
774         if (!m_freewheel_thread_active) {
775                 return true;
776         }
777
778         DEBUG_AUDIO("Signaling freewheel thread to stop\n");
779
780         pthread_mutex_lock (&m_freewheel_mutex);
781         pthread_cond_signal (&m_freewheel_signal);
782         pthread_mutex_unlock (&m_freewheel_mutex);
783
784         if (pthread_join (m_pthread_freewheel, &status) != 0) {
785                 DEBUG_AUDIO("Failed to stop freewheel thread\n");
786                 return false;
787         }
788
789         return true;
790 }
791
792 void*
793 PortAudioBackend::freewheel_process_thread()
794 {
795         m_freewheel_thread_active = true;
796
797         bool first_run = false;
798
799         pthread_mutex_lock (&m_freewheel_mutex);
800
801         while(_run) {
802                 // check if we should run,
803                 if (_freewheeling != _freewheel) {
804                         if (!_freewheeling) {
805                                 DEBUG_AUDIO("Leaving freewheel\n");
806                                 _freewheel = false; // first mark as disabled
807                                 _reinit_thread_callback = true; // hand over _main_thread
808                                 _freewheel_ack = false; // prepare next handshake
809                                 _midiio->set_enabled(true);
810                         } else {
811                                 first_run = true;
812                                 _freewheel = true;
813                         }
814                 }
815
816                 if (!_freewheel || !_freewheel_ack) {
817                         // wait for a change, we use a timed wait to
818                         // terminate early in case some error sets _run = 0
819                         struct timeval tv;
820                         struct timespec ts;
821                         gettimeofday (&tv, NULL);
822                         ts.tv_sec = tv.tv_sec + 3;
823                         ts.tv_nsec = 0;
824                         DEBUG_AUDIO("Waiting for freewheel change\n");
825                         pthread_cond_timedwait (&m_freewheel_signal, &m_freewheel_mutex, &ts);
826                         continue;
827                 }
828
829                 if (first_run) {
830                         // tell the engine we're ready to GO.
831                         engine.freewheel_callback (_freewheeling);
832                         first_run = false;
833                         m_main_thread = pthread_self();
834                         AudioEngine::thread_init_callback (this);
835                         _midiio->set_enabled(false);
836                 }
837
838                 if (!blocking_process_freewheel()) {
839                         break;
840                 }
841         }
842
843         pthread_mutex_unlock (&m_freewheel_mutex);
844
845         m_freewheel_thread_active = false;
846
847         if (_run) {
848                 // engine.process_callback() returner error
849                 engine.halted_callback("CoreAudio Freehweeling aborted.");
850         }
851         return 0;
852 }
853
854 int
855 PortAudioBackend::freewheel (bool onoff)
856 {
857         if (onoff == _freewheeling) {
858                 return 0;
859         }
860         _freewheeling = onoff;
861
862         if (0 == pthread_mutex_trylock (&m_freewheel_mutex)) {
863                 pthread_cond_signal (&m_freewheel_signal);
864                 pthread_mutex_unlock (&m_freewheel_mutex);
865         }
866         return 0;
867 }
868
869 float
870 PortAudioBackend::dsp_load () const
871 {
872         return 100.f * _dsp_load;
873 }
874
875 size_t
876 PortAudioBackend::raw_buffer_size (DataType t)
877 {
878         switch (t) {
879         case DataType::AUDIO:
880                 return _samples_per_period * sizeof(Sample);
881         case DataType::MIDI:
882                 return _max_buffer_size; // XXX not really limited
883         }
884         return 0;
885 }
886
887 /* Process time */
888 framepos_t
889 PortAudioBackend::sample_time ()
890 {
891         return _processed_samples;
892 }
893
894 framepos_t
895 PortAudioBackend::sample_time_at_cycle_start ()
896 {
897         return _processed_samples;
898 }
899
900 pframes_t
901 PortAudioBackend::samples_since_cycle_start ()
902 {
903         if (!_active || !_run || _freewheeling || _freewheel) {
904                 return 0;
905         }
906         if (!m_cycle_timer.valid()) {
907                 return 0;
908         }
909
910         return m_cycle_timer.samples_since_cycle_start (PBD::get_microseconds());
911 }
912
913 int
914 PortAudioBackend::name_to_id(std::string device_name) const {
915         uint32_t device_id = UINT32_MAX;
916         std::map<int, std::string> devices;
917         _pcmio->input_device_list(devices);
918         _pcmio->output_device_list(devices);
919
920         for (std::map<int, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
921                 if (i->second == device_name) {
922                         device_id = i->first;
923                         break;
924                 }
925         }
926         return device_id;
927 }
928
929 bool
930 PortAudioBackend::set_mmcss_pro_audio (HANDLE* task_handle)
931 {
932         bool mmcss_success = PBD::MMCSS::set_thread_characteristics ("Pro Audio", task_handle);
933
934         if (!mmcss_success) {
935                 PBD::warning << get_error_string(SettingAudioThreadPriorityError) << endmsg;
936                 return false;
937         } else {
938                 DEBUG_THREADS("Thread characteristics set to Pro Audio\n");
939         }
940
941         bool mmcss_priority =
942                 PBD::MMCSS::set_thread_priority(*task_handle, PBD::MMCSS::AVRT_PRIORITY_NORMAL);
943
944         if (!mmcss_priority) {
945                 PBD::warning << get_error_string(SettingAudioThreadPriorityError) << endmsg;
946                 return false;
947         } else {
948                 DEBUG_THREADS("Thread priority set to AVRT_PRIORITY_NORMAL\n");
949         }
950
951         return true;
952 }
953
954 bool
955 PortAudioBackend::reset_mmcss (HANDLE task_handle)
956 {
957         if (!PBD::MMCSS::revert_thread_characteristics(task_handle)) {
958                 DEBUG_THREADS("Unable to reset process thread characteristics\n");
959                 return false;
960         }
961         return true;
962 }
963
964 void *
965 PortAudioBackend::portaudio_process_thread (void *arg)
966 {
967         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
968         boost::function<void ()> f = td->f;
969         delete td;
970
971 #ifdef USE_MMCSS_THREAD_PRIORITIES
972         HANDLE task_handle;
973         bool mmcss_success = set_mmcss_pro_audio (&task_handle);
974 #endif
975
976         DWORD tid = GetCurrentThreadId ();
977         DEBUG_THREADS (string_compose ("Process Thread Child ID: %1\n", tid));
978
979         f ();
980
981 #ifdef USE_MMCSS_THREAD_PRIORITIES
982         if (mmcss_success) {
983                 reset_mmcss (task_handle);
984         }
985 #endif
986
987         return 0;
988 }
989
990 int
991 PortAudioBackend::create_process_thread (boost::function<void()> func)
992 {
993         pthread_t thread_id;
994         pthread_attr_t attr;
995         size_t stacksize = 100000;
996
997         ThreadData* td = new ThreadData (this, func, stacksize);
998
999         if (_realtime_pthread_create (SCHED_FIFO, -21, stacksize,
1000                                 &thread_id, portaudio_process_thread, td)) {
1001                 pthread_attr_init (&attr);
1002                 pthread_attr_setstacksize (&attr, stacksize);
1003                 if (pthread_create (&thread_id, &attr, portaudio_process_thread, td)) {
1004                         DEBUG_AUDIO("Cannot create process thread.");
1005                         pthread_attr_destroy (&attr);
1006                         return -1;
1007                 }
1008                 pthread_attr_destroy (&attr);
1009         }
1010
1011         _threads.push_back (thread_id);
1012         return 0;
1013 }
1014
1015 int
1016 PortAudioBackend::join_process_threads ()
1017 {
1018         int rv = 0;
1019
1020         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
1021         {
1022                 void *status;
1023                 if (pthread_join (*i, &status)) {
1024                         DEBUG_AUDIO("Cannot terminate process thread.");
1025                         rv -= 1;
1026                 }
1027         }
1028         _threads.clear ();
1029         return rv;
1030 }
1031
1032 bool
1033 PortAudioBackend::in_process_thread ()
1034 {
1035 #ifdef USE_BLOCKING_API
1036         if (pthread_equal (_main_blocking_thread, pthread_self()) != 0) {
1037                 return true;
1038         }
1039 #else
1040         if (pthread_equal (m_main_thread, pthread_self()) != 0) {
1041                 return true;
1042         }
1043 #endif
1044
1045         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
1046         {
1047                 if (pthread_equal (*i, pthread_self ()) != 0) {
1048                         return true;
1049                 }
1050         }
1051         return false;
1052 }
1053
1054 uint32_t
1055 PortAudioBackend::process_thread_count ()
1056 {
1057         return _threads.size ();
1058 }
1059
1060 void
1061 PortAudioBackend::update_latencies ()
1062 {
1063         // trigger latency callback in RT thread (locked graph)
1064         port_connect_add_remove_callback();
1065 }
1066
1067 /* PORTENGINE API */
1068
1069 void*
1070 PortAudioBackend::private_handle () const
1071 {
1072         return NULL;
1073 }
1074
1075 const std::string&
1076 PortAudioBackend::my_name () const
1077 {
1078         return _instance_name;
1079 }
1080
1081 bool
1082 PortAudioBackend::available () const
1083 {
1084         return _run && _active;
1085 }
1086
1087 uint32_t
1088 PortAudioBackend::port_name_size () const
1089 {
1090         return 256;
1091 }
1092
1093 int
1094 PortAudioBackend::set_port_name (PortEngine::PortHandle port, const std::string& name)
1095 {
1096         if (!valid_port (port)) {
1097                 DEBUG_PORTS("set_port_name: Invalid Port(s)\n");
1098                 return -1;
1099         }
1100         return static_cast<PamPort*>(port)->set_name (_instance_name + ":" + name);
1101 }
1102
1103 std::string
1104 PortAudioBackend::get_port_name (PortEngine::PortHandle port) const
1105 {
1106         if (!valid_port (port)) {
1107                 DEBUG_PORTS("get_port_name: Invalid Port(s)\n");
1108                 return std::string ();
1109         }
1110         return static_cast<PamPort*>(port)->name ();
1111 }
1112
1113 int
1114 PortAudioBackend::get_port_property (PortHandle port,
1115                                      const std::string& key,
1116                                      std::string& value,
1117                                      std::string& type) const
1118 {
1119         if (!valid_port (port)) {
1120                 DEBUG_PORTS("get_port_name: Invalid Port(s)\n");
1121                 return -1;
1122         }
1123
1124         if (key == "http://jackaudio.org/metadata/pretty-name") {
1125                 type = "";
1126                 value = static_cast<PamPort*>(port)->pretty_name ();
1127                 if (!value.empty()) {
1128                         return 0;
1129                 }
1130         }
1131         return -1;
1132 }
1133
1134 PortEngine::PortHandle
1135 PortAudioBackend::get_port_by_name (const std::string& name) const
1136 {
1137         PortHandle port = (PortHandle) find_port (name);
1138         return port;
1139 }
1140
1141 int
1142 PortAudioBackend::get_ports (
1143                 const std::string& port_name_pattern,
1144                 DataType type, PortFlags flags,
1145                 std::vector<std::string>& port_names) const
1146 {
1147         int rv = 0;
1148         regex_t port_regex;
1149         bool use_regexp = false;
1150         if (port_name_pattern.size () > 0) {
1151                 if (!regcomp (&port_regex, port_name_pattern.c_str (), REG_EXTENDED|REG_NOSUB)) {
1152                         use_regexp = true;
1153                 }
1154         }
1155         for (size_t i = 0; i < _ports.size (); ++i) {
1156                 PamPort* port = _ports[i];
1157                 if ((port->type () == type) && flags == (port->flags () & flags)) {
1158                         if (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) {
1159                                 port_names.push_back (port->name ());
1160                                 ++rv;
1161                         }
1162                 }
1163         }
1164         if (use_regexp) {
1165                 regfree (&port_regex);
1166         }
1167         return rv;
1168 }
1169
1170 DataType
1171 PortAudioBackend::port_data_type (PortEngine::PortHandle port) const
1172 {
1173         if (!valid_port (port)) {
1174                 return DataType::NIL;
1175         }
1176         return static_cast<PamPort*>(port)->type ();
1177 }
1178
1179 PortEngine::PortHandle
1180 PortAudioBackend::register_port (
1181                 const std::string& name,
1182                 ARDOUR::DataType type,
1183                 ARDOUR::PortFlags flags)
1184 {
1185         if (name.size () == 0) { return 0; }
1186         if (flags & IsPhysical) { return 0; }
1187         return add_port (_instance_name + ":" + name, type, flags);
1188 }
1189
1190 PortEngine::PortHandle
1191 PortAudioBackend::add_port (
1192                 const std::string& name,
1193                 ARDOUR::DataType type,
1194                 ARDOUR::PortFlags flags)
1195 {
1196         assert(name.size ());
1197         if (find_port (name)) {
1198                 DEBUG_PORTS(
1199                     string_compose("register_port: Port already exists: (%1)\n", name));
1200                 return 0;
1201         }
1202         PamPort* port = NULL;
1203         switch (type) {
1204         case DataType::AUDIO:
1205                 port = new PortAudioPort(*this, name, flags);
1206                 break;
1207         case DataType::MIDI:
1208                 port = new PortMidiPort(*this, name, flags);
1209                 break;
1210         default:
1211                 DEBUG_PORTS("register_port: Invalid Data Type.\n");
1212                 return 0;
1213         }
1214
1215         _ports.push_back (port);
1216
1217         return port;
1218 }
1219
1220 void
1221 PortAudioBackend::unregister_port (PortEngine::PortHandle port_handle)
1222 {
1223         if (!_run) {
1224                 return;
1225         }
1226         PamPort* port = static_cast<PamPort*>(port_handle);
1227         std::vector<PamPort*>::iterator i = std::find (_ports.begin (), _ports.end (), static_cast<PamPort*>(port_handle));
1228         if (i == _ports.end ()) {
1229                 DEBUG_PORTS("unregister_port: Failed to find port\n");
1230                 return;
1231         }
1232         disconnect_all(port_handle);
1233         _ports.erase (i);
1234         delete port;
1235 }
1236
1237 int
1238 PortAudioBackend::register_system_audio_ports()
1239 {
1240         LatencyRange lr;
1241
1242         const uint32_t a_ins = _n_inputs;
1243         const uint32_t a_out = _n_outputs;
1244
1245         // XXX PA reported stream latencies don't match measurements
1246         const uint32_t portaudio_reported_input_latency =  _samples_per_period ; //  _pcmio->capture_latency();
1247         const uint32_t portaudio_reported_output_latency = /* _samples_per_period + */ _pcmio->playback_latency();
1248
1249         /* audio ports */
1250         lr.min = lr.max = portaudio_reported_input_latency + (_measure_latency ? 0 : _systemic_audio_input_latency);
1251         for (uint32_t i = 0; i < a_ins; ++i) {
1252                 char tmp[64];
1253                 snprintf(tmp, sizeof(tmp), "system:capture_%d", i+1);
1254                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
1255                 if (!p) return -1;
1256                 set_latency_range (p, false, lr);
1257                 PortAudioPort* audio_port = static_cast<PortAudioPort*>(p);
1258                 audio_port->set_pretty_name (
1259                     _pcmio->get_input_channel_name (name_to_id (_input_audio_device), i));
1260                 _system_inputs.push_back (audio_port);
1261         }
1262
1263         lr.min = lr.max = portaudio_reported_output_latency + (_measure_latency ? 0 : _systemic_audio_output_latency);
1264         for (uint32_t i = 0; i < a_out; ++i) {
1265                 char tmp[64];
1266                 snprintf(tmp, sizeof(tmp), "system:playback_%d", i+1);
1267                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
1268                 if (!p) return -1;
1269                 set_latency_range (p, true, lr);
1270                 PortAudioPort* audio_port = static_cast<PortAudioPort*>(p);
1271                 audio_port->set_pretty_name (
1272                     _pcmio->get_output_channel_name (name_to_id (_output_audio_device), i));
1273                 _system_outputs.push_back(audio_port);
1274         }
1275         return 0;
1276 }
1277
1278 int
1279 PortAudioBackend::register_system_midi_ports()
1280 {
1281         if (_midi_driver_option == get_standard_device_name(DeviceNone)) {
1282                 DEBUG_MIDI("No MIDI backend selected, not system midi ports available\n");
1283                 return 0;
1284         }
1285
1286         LatencyRange lr;
1287         lr.min = lr.max = _samples_per_period;
1288
1289         const std::vector<WinMMEMidiInputDevice*> inputs = _midiio->get_inputs();
1290
1291         for (std::vector<WinMMEMidiInputDevice*>::const_iterator i = inputs.begin ();
1292              i != inputs.end ();
1293              ++i) {
1294                 std::string port_name = "system_midi:" + (*i)->name() + " capture";
1295                 PortHandle p =
1296                     add_port (port_name,
1297                               DataType::MIDI,
1298                               static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
1299                 if (!p) return -1;
1300                 set_latency_range (p, false, lr);
1301                 PortMidiPort* midi_port = static_cast<PortMidiPort*>(p);
1302                 midi_port->set_pretty_name ((*i)->name());
1303                 _system_midi_in.push_back (midi_port);
1304                 DEBUG_MIDI (string_compose ("Registered MIDI input port: %1\n", port_name));
1305         }
1306
1307         const std::vector<WinMMEMidiOutputDevice*> outputs = _midiio->get_outputs();
1308
1309         for (std::vector<WinMMEMidiOutputDevice*>::const_iterator i = outputs.begin ();
1310              i != outputs.end ();
1311              ++i) {
1312                 std::string port_name = "system_midi:" + (*i)->name() + " playback";
1313                 PortHandle p =
1314                     add_port (port_name,
1315                               DataType::MIDI,
1316                               static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
1317                 if (!p) return -1;
1318                 set_latency_range (p, false, lr);
1319                 PortMidiPort* midi_port = static_cast<PortMidiPort*>(p);
1320                 midi_port->set_n_periods(2);
1321                 midi_port->set_pretty_name ((*i)->name());
1322                 _system_midi_out.push_back (midi_port);
1323                 DEBUG_MIDI (string_compose ("Registered MIDI output port: %1\n", port_name));
1324         }
1325         return 0;
1326 }
1327
1328 void
1329 PortAudioBackend::unregister_ports (bool system_only)
1330 {
1331         size_t i = 0;
1332         _system_inputs.clear();
1333         _system_outputs.clear();
1334         _system_midi_in.clear();
1335         _system_midi_out.clear();
1336         while (i <  _ports.size ()) {
1337                 PamPort* port = _ports[i];
1338                 if (! system_only || (port->is_physical () && port->is_terminal ())) {
1339                         port->disconnect_all ();
1340                         delete port;
1341                         _ports.erase (_ports.begin() + i);
1342                 } else {
1343                         ++i;
1344                 }
1345         }
1346 }
1347
1348 int
1349 PortAudioBackend::connect (const std::string& src, const std::string& dst)
1350 {
1351         PamPort* src_port = find_port (src);
1352         PamPort* dst_port = find_port (dst);
1353
1354         if (!src_port) {
1355                 DEBUG_PORTS(string_compose("connect: Invalid Source port: (%1)\n", src));
1356                 return -1;
1357         }
1358         if (!dst_port) {
1359                 DEBUG_PORTS(string_compose("connect: Invalid Destination port: (%1)\n", dst));
1360                 return -1;
1361         }
1362         return src_port->connect (dst_port);
1363 }
1364
1365 int
1366 PortAudioBackend::disconnect (const std::string& src, const std::string& dst)
1367 {
1368         PamPort* src_port = find_port (src);
1369         PamPort* dst_port = find_port (dst);
1370
1371         if (!src_port || !dst_port) {
1372                 DEBUG_PORTS("disconnect: Invalid Port(s)\n");
1373                 return -1;
1374         }
1375         return src_port->disconnect (dst_port);
1376 }
1377
1378 int
1379 PortAudioBackend::connect (PortEngine::PortHandle src, const std::string& dst)
1380 {
1381         PamPort* dst_port = find_port (dst);
1382         if (!valid_port (src)) {
1383                 DEBUG_PORTS("connect: Invalid Source Port Handle\n");
1384                 return -1;
1385         }
1386         if (!dst_port) {
1387                 DEBUG_PORTS(string_compose("connect: Invalid Destination Port (%1)\n", dst));
1388                 return -1;
1389         }
1390         return static_cast<PamPort*>(src)->connect (dst_port);
1391 }
1392
1393 int
1394 PortAudioBackend::disconnect (PortEngine::PortHandle src, const std::string& dst)
1395 {
1396         PamPort* dst_port = find_port (dst);
1397         if (!valid_port (src) || !dst_port) {
1398                 DEBUG_PORTS("disconnect: Invalid Port(s)\n");
1399                 return -1;
1400         }
1401         return static_cast<PamPort*>(src)->disconnect (dst_port);
1402 }
1403
1404 int
1405 PortAudioBackend::disconnect_all (PortEngine::PortHandle port)
1406 {
1407         if (!valid_port (port)) {
1408                 DEBUG_PORTS("disconnect_all: Invalid Port\n");
1409                 return -1;
1410         }
1411         static_cast<PamPort*>(port)->disconnect_all ();
1412         return 0;
1413 }
1414
1415 bool
1416 PortAudioBackend::connected (PortEngine::PortHandle port, bool /* process_callback_safe*/)
1417 {
1418         if (!valid_port (port)) {
1419                 DEBUG_PORTS("disconnect_all: Invalid Port\n");
1420                 return false;
1421         }
1422         return static_cast<PamPort*>(port)->is_connected ();
1423 }
1424
1425 bool
1426 PortAudioBackend::connected_to (PortEngine::PortHandle src, const std::string& dst, bool /*process_callback_safe*/)
1427 {
1428         PamPort* dst_port = find_port (dst);
1429         if (!valid_port (src) || !dst_port) {
1430                 DEBUG_PORTS("connected_to: Invalid Port\n");
1431                 return false;
1432         }
1433         return static_cast<PamPort*>(src)->is_connected (dst_port);
1434 }
1435
1436 bool
1437 PortAudioBackend::physically_connected (PortEngine::PortHandle port, bool /*process_callback_safe*/)
1438 {
1439         if (!valid_port (port)) {
1440                 DEBUG_PORTS("physically_connected: Invalid Port\n");
1441                 return false;
1442         }
1443         return static_cast<PamPort*>(port)->is_physically_connected ();
1444 }
1445
1446 int
1447 PortAudioBackend::get_connections (PortEngine::PortHandle port, std::vector<std::string>& names, bool /*process_callback_safe*/)
1448 {
1449         if (!valid_port (port)) {
1450                 DEBUG_PORTS("get_connections: Invalid Port\n");
1451                 return -1;
1452         }
1453
1454         assert (0 == names.size ());
1455
1456         const std::vector<PamPort*>& connected_ports = static_cast<PamPort*>(port)->get_connections ();
1457
1458         for (std::vector<PamPort*>::const_iterator i = connected_ports.begin (); i != connected_ports.end (); ++i) {
1459                 names.push_back ((*i)->name ());
1460         }
1461
1462         return (int)names.size ();
1463 }
1464
1465 /* MIDI */
1466 int
1467 PortAudioBackend::midi_event_get (
1468                 pframes_t& timestamp,
1469                 size_t& size, uint8_t** buf, void* port_buffer,
1470                 uint32_t event_index)
1471 {
1472         if (!buf || !port_buffer) return -1;
1473         PortMidiBuffer& source = * static_cast<PortMidiBuffer*>(port_buffer);
1474         if (event_index >= source.size ()) {
1475                 return -1;
1476         }
1477         PortMidiEvent * const event = source[event_index].get ();
1478
1479         timestamp = event->timestamp ();
1480         size = event->size ();
1481         *buf = event->data ();
1482         return 0;
1483 }
1484
1485 int
1486 PortAudioBackend::midi_event_put (
1487                 void* port_buffer,
1488                 pframes_t timestamp,
1489                 const uint8_t* buffer, size_t size)
1490 {
1491         if (!buffer || !port_buffer) return -1;
1492         PortMidiBuffer& dst = * static_cast<PortMidiBuffer*>(port_buffer);
1493         if (dst.size () && (pframes_t)dst.back ()->timestamp () > timestamp) {
1494                 // nevermind, ::get_buffer() sorts events
1495                 DEBUG_MIDI (string_compose ("PortMidiBuffer: unordered event: %1 > %2\n",
1496                                             (pframes_t)dst.back ()->timestamp (),
1497                                             timestamp));
1498         }
1499         dst.push_back (boost::shared_ptr<PortMidiEvent>(new PortMidiEvent (timestamp, buffer, size)));
1500         return 0;
1501 }
1502
1503 uint32_t
1504 PortAudioBackend::get_midi_event_count (void* port_buffer)
1505 {
1506         if (!port_buffer) return 0;
1507         return static_cast<PortMidiBuffer*>(port_buffer)->size ();
1508 }
1509
1510 void
1511 PortAudioBackend::midi_clear (void* port_buffer)
1512 {
1513         if (!port_buffer) return;
1514         PortMidiBuffer * buf = static_cast<PortMidiBuffer*>(port_buffer);
1515         assert (buf);
1516         buf->clear ();
1517 }
1518
1519 /* Monitoring */
1520
1521 bool
1522 PortAudioBackend::can_monitor_input () const
1523 {
1524         return false;
1525 }
1526
1527 int
1528 PortAudioBackend::request_input_monitoring (PortEngine::PortHandle, bool)
1529 {
1530         return -1;
1531 }
1532
1533 int
1534 PortAudioBackend::ensure_input_monitoring (PortEngine::PortHandle, bool)
1535 {
1536         return -1;
1537 }
1538
1539 bool
1540 PortAudioBackend::monitoring_input (PortEngine::PortHandle)
1541 {
1542         return false;
1543 }
1544
1545 /* Latency management */
1546
1547 void
1548 PortAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range)
1549 {
1550         if (!valid_port (port)) {
1551                 DEBUG_PORTS("PamPort::set_latency_range (): invalid port.\n");
1552         }
1553         static_cast<PamPort*>(port)->set_latency_range (latency_range, for_playback);
1554 }
1555
1556 LatencyRange
1557 PortAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback)
1558 {
1559         LatencyRange r;
1560         if (!valid_port (port)) {
1561                 DEBUG_PORTS("PamPort::get_latency_range (): invalid port.\n");
1562                 r.min = 0;
1563                 r.max = 0;
1564                 return r;
1565         }
1566         PamPort* p = static_cast<PamPort*>(port);
1567         assert(p);
1568
1569         r = p->latency_range (for_playback);
1570         // TODO MIDI
1571         if (p->is_physical() && p->is_terminal() && p->type() == DataType::AUDIO) {
1572                 if (p->is_input() && for_playback) {
1573                         r.min += _samples_per_period;
1574                         r.max += _samples_per_period;
1575                 }
1576                 if (p->is_output() && !for_playback) {
1577                         r.min += _samples_per_period;
1578                         r.max += _samples_per_period;
1579                 }
1580         }
1581         return r;
1582 }
1583
1584 /* Discovering physical ports */
1585
1586 bool
1587 PortAudioBackend::port_is_physical (PortEngine::PortHandle port) const
1588 {
1589         if (!valid_port (port)) {
1590                 DEBUG_PORTS("PamPort::port_is_physical (): invalid port.\n");
1591                 return false;
1592         }
1593         return static_cast<PamPort*>(port)->is_physical ();
1594 }
1595
1596 void
1597 PortAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>& port_names)
1598 {
1599         for (size_t i = 0; i < _ports.size (); ++i) {
1600                 PamPort* port = _ports[i];
1601                 if ((port->type () == type) && port->is_input () && port->is_physical ()) {
1602                         port_names.push_back (port->name ());
1603                 }
1604         }
1605 }
1606
1607 void
1608 PortAudioBackend::get_physical_inputs (DataType type, std::vector<std::string>& port_names)
1609 {
1610         for (size_t i = 0; i < _ports.size (); ++i) {
1611                 PamPort* port = _ports[i];
1612                 if ((port->type () == type) && port->is_output () && port->is_physical ()) {
1613                         port_names.push_back (port->name ());
1614                 }
1615         }
1616 }
1617
1618 ChanCount
1619 PortAudioBackend::n_physical_outputs () const
1620 {
1621         int n_midi = 0;
1622         int n_audio = 0;
1623         for (size_t i = 0; i < _ports.size (); ++i) {
1624                 PamPort* port = _ports[i];
1625                 if (port->is_output () && port->is_physical ()) {
1626                         switch (port->type ()) {
1627                         case DataType::AUDIO:
1628                                 ++n_audio;
1629                                 break;
1630                         case DataType::MIDI:
1631                                 ++n_midi;
1632                                 break;
1633                         default:
1634                                 break;
1635                         }
1636                 }
1637         }
1638         ChanCount cc;
1639         cc.set (DataType::AUDIO, n_audio);
1640         cc.set (DataType::MIDI, n_midi);
1641         return cc;
1642 }
1643
1644 ChanCount
1645 PortAudioBackend::n_physical_inputs () const
1646 {
1647         int n_midi = 0;
1648         int n_audio = 0;
1649         for (size_t i = 0; i < _ports.size (); ++i) {
1650                 PamPort* port = _ports[i];
1651                 if (port->is_input () && port->is_physical ()) {
1652                         switch (port->type ()) {
1653                         case DataType::AUDIO:
1654                                 ++n_audio;
1655                                 break;
1656                         case DataType::MIDI:
1657                                 ++n_midi;
1658                                 break;
1659                         default:
1660                                 break;
1661                         }
1662                 }
1663         }
1664         ChanCount cc;
1665         cc.set (DataType::AUDIO, n_audio);
1666         cc.set (DataType::MIDI, n_midi);
1667         return cc;
1668 }
1669
1670 /* Getting access to the data buffer for a port */
1671
1672 void*
1673 PortAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes)
1674 {
1675         if (!port || !valid_port (port)) return NULL;
1676         return static_cast<PamPort*>(port)->get_buffer (nframes);
1677 }
1678
1679
1680 void *
1681 PortAudioBackend::main_blocking_process_thread ()
1682 {
1683         AudioEngine::thread_init_callback (this);
1684         _active = true;
1685         _processed_samples = 0;
1686
1687         manager.registration_callback();
1688         manager.graph_order_callback();
1689
1690         if (_pcmio->start_stream() != paNoError) {
1691                 _pcmio->close_stream ();
1692                 _active = false;
1693                 engine.halted_callback(get_error_string(AudioDeviceIOError).c_str());
1694         }
1695
1696 #ifdef USE_MMCSS_THREAD_PRIORITIES
1697         HANDLE task_handle;
1698         bool mmcss_success = set_mmcss_pro_audio (&task_handle);
1699 #endif
1700
1701         DWORD tid = GetCurrentThreadId ();
1702         DEBUG_THREADS (string_compose ("Process Thread Master ID: %1\n", tid));
1703
1704         while (_run) {
1705
1706                 if (_freewheeling != _freewheel) {
1707                         _freewheel = _freewheeling;
1708                         engine.freewheel_callback (_freewheel);
1709                 }
1710
1711                 if (!_freewheel) {
1712
1713                         switch (_pcmio->next_cycle (_samples_per_period)) {
1714                         case 0: // OK
1715                                 break;
1716                         case 1:
1717                                 DEBUG_AUDIO("PortAudio: Xrun\n");
1718                                 engine.Xrun();
1719                                 break;
1720                         default:
1721                                 PBD::error << get_error_string(AudioDeviceIOError) << endmsg;
1722                                 break;
1723                         }
1724
1725                         if (!blocking_process_main(_pcmio->get_capture_buffer(),
1726                                                    _pcmio->get_playback_buffer())) {
1727                                 return 0;
1728                         }
1729                 } else {
1730
1731                         if (!blocking_process_freewheel()) {
1732                                 return 0;
1733                         }
1734                 }
1735
1736                 process_port_connection_changes();
1737         }
1738         _pcmio->close_stream();
1739         _active = false;
1740         if (_run) {
1741                 engine.halted_callback(get_error_string(AudioDeviceIOError).c_str());
1742         }
1743
1744 #ifdef USE_MMCSS_THREAD_PRIORITIES
1745         if (mmcss_success) {
1746                 reset_mmcss(task_handle);
1747         }
1748 #endif
1749
1750         return 0;
1751 }
1752
1753 bool
1754 PortAudioBackend::blocking_process_main(const float* interleaved_input_data,
1755                                         float* interleaved_output_data)
1756 {
1757         uint32_t i = 0;
1758         int64_t min_elapsed_us = 1000000;
1759         int64_t max_elapsed_us = 0;
1760
1761         m_dsp_calc.set_start_timestamp_us (PBD::get_microseconds());
1762
1763         i = 0;
1764         /* Copy input audio data into input port buffers */
1765         for (std::vector<PamPort*>::const_iterator it = _system_inputs.begin();
1766              it != _system_inputs.end();
1767              ++it, ++i) {
1768                 assert(_system_inputs.size() == _pcmio->n_capture_channels());
1769                 uint32_t channels = _system_inputs.size();
1770                 float* input_port_buffer = (float*)(*it)->get_buffer(_samples_per_period);
1771                 deinterleave_audio_data(
1772                     interleaved_input_data, input_port_buffer, _samples_per_period, i, channels);
1773         }
1774
1775         process_incoming_midi ();
1776
1777         /* clear output buffers */
1778         for (std::vector<PamPort*>::const_iterator it = _system_outputs.begin();
1779              it != _system_outputs.end();
1780              ++it) {
1781                 memset((*it)->get_buffer(_samples_per_period),
1782                        0,
1783                        _samples_per_period * sizeof(Sample));
1784         }
1785
1786         m_last_cycle_start = m_cycle_timer.get_start();
1787         m_cycle_timer.reset_start(PBD::get_microseconds());
1788         m_cycle_count++;
1789
1790         uint64_t cycle_diff_us = (m_cycle_timer.get_start() - m_last_cycle_start);
1791         int64_t deviation_us = (cycle_diff_us - m_cycle_timer.get_length_us());
1792         m_total_deviation_us += ::llabs(deviation_us);
1793         m_max_deviation_us =
1794             std::max(m_max_deviation_us, (uint64_t)::llabs(deviation_us));
1795
1796         if ((m_cycle_count % 1000) == 0) {
1797                 uint64_t mean_deviation_us = m_total_deviation_us / m_cycle_count;
1798                 DEBUG_TIMING(string_compose("Mean avg cycle deviation: %1(ms), max %2(ms)\n",
1799                                             mean_deviation_us * 1e-3,
1800                                             m_max_deviation_us * 1e-3));
1801         }
1802
1803         if (::llabs(deviation_us) > m_cycle_timer.get_length_us()) {
1804                 DEBUG_TIMING(
1805                     string_compose("time between process(ms): %1, Est(ms): %2, Dev(ms): %3\n",
1806                                    cycle_diff_us * 1e-3,
1807                                    m_cycle_timer.get_length_us() * 1e-3,
1808                                    deviation_us * 1e-3));
1809         }
1810
1811         /* call engine process callback */
1812         if (engine.process_callback(_samples_per_period)) {
1813                 _pcmio->close_stream();
1814                 _active = false;
1815                 return false;
1816         }
1817
1818         process_outgoing_midi ();
1819
1820         /* write back audio */
1821         i = 0;
1822         for (std::vector<PamPort*>::const_iterator it = _system_outputs.begin();
1823              it != _system_outputs.end();
1824              ++it, ++i) {
1825                 assert(_system_outputs.size() == _pcmio->n_playback_channels());
1826                 const uint32_t channels = _system_outputs.size();
1827                 float* output_port_buffer = (float*)(*it)->get_buffer(_samples_per_period);
1828                 interleave_audio_data(
1829                     output_port_buffer, interleaved_output_data, _samples_per_period, i, channels);
1830         }
1831
1832         _processed_samples += _samples_per_period;
1833
1834         /* calculate DSP load */
1835         m_dsp_calc.set_stop_timestamp_us (PBD::get_microseconds());
1836         _dsp_load = m_dsp_calc.get_dsp_load();
1837
1838         DEBUG_TIMING(string_compose("DSP Load: %1\n", _dsp_load));
1839
1840         max_elapsed_us = std::max(m_dsp_calc.elapsed_time_us(), max_elapsed_us);
1841         min_elapsed_us = std::min(m_dsp_calc.elapsed_time_us(), min_elapsed_us);
1842         if ((m_cycle_count % 1000) == 0) {
1843                 DEBUG_TIMING(string_compose("Elapsed process time(usecs) max: %1, min: %2\n",
1844                                             max_elapsed_us,
1845                                             min_elapsed_us));
1846         }
1847
1848         return true;
1849 }
1850
1851 bool
1852 PortAudioBackend::blocking_process_freewheel()
1853 {
1854         // zero audio input buffers
1855         for (std::vector<PamPort*>::const_iterator it = _system_inputs.begin();
1856              it != _system_inputs.end();
1857              ++it) {
1858                 memset((*it)->get_buffer(_samples_per_period),
1859                        0,
1860                        _samples_per_period * sizeof(Sample));
1861         }
1862
1863         // TODO clear midi or stop midi recv when entering fwheelin'
1864
1865         if (engine.process_callback(_samples_per_period)) {
1866                 _pcmio->close_stream();
1867                 _active = false;
1868                 return false;
1869         }
1870
1871         // drop all outgoing MIDI messages
1872         for (std::vector<PamPort*>::const_iterator it = _system_midi_out.begin();
1873              it != _system_midi_out.end();
1874              ++it) {
1875                 void* bptr = (*it)->get_buffer(0);
1876                 midi_clear(bptr);
1877         }
1878
1879         _dsp_load = 1.0;
1880         Glib::usleep(100); // don't hog cpu
1881         return true;
1882 }
1883
1884 void
1885 PortAudioBackend::process_incoming_midi ()
1886 {
1887         uint32_t i = 0;
1888         for (std::vector<PamPort*>::const_iterator it = _system_midi_in.begin();
1889              it != _system_midi_in.end();
1890              ++it, ++i) {
1891                 PortMidiBuffer* mbuf = static_cast<PortMidiBuffer*>((*it)->get_buffer(0));
1892                 mbuf->clear();
1893                 uint64_t timestamp;
1894                 pframes_t sample_offset;
1895                 uint8_t data[256];
1896                 size_t size = sizeof(data);
1897                 while (_midiio->dequeue_input_event(i,
1898                                                     m_cycle_timer.get_start(),
1899                                                     m_cycle_timer.get_next_start(),
1900                                                     timestamp,
1901                                                     data,
1902                                                     size)) {
1903                         sample_offset = m_cycle_timer.samples_since_cycle_start(timestamp);
1904                         midi_event_put(mbuf, sample_offset, data, size);
1905                         DEBUG_MIDI(string_compose("Dequeuing incoming MIDI data for device: %1 "
1906                                                   "sample_offset: %2 timestamp: %3, size: %4\n",
1907                                                   _midiio->get_inputs()[i]->name(),
1908                                                   sample_offset,
1909                                                   timestamp,
1910                                                   size));
1911                         size = sizeof(data);
1912                 }
1913         }
1914 }
1915
1916 void
1917 PortAudioBackend::process_outgoing_midi ()
1918 {
1919         /* mixdown midi */
1920         for (std::vector<PamPort*>::iterator it = _system_midi_out.begin();
1921              it != _system_midi_out.end();
1922              ++it) {
1923                 static_cast<PortMidiPort*>(*it)->next_period();
1924         }
1925         /* queue outgoing midi */
1926         uint32_t i = 0;
1927         for (std::vector<PamPort*>::const_iterator it = _system_midi_out.begin();
1928              it != _system_midi_out.end();
1929              ++it, ++i) {
1930                 const PortMidiBuffer* src =
1931                     static_cast<const PortMidiPort*>(*it)->const_buffer();
1932
1933                 for (PortMidiBuffer::const_iterator mit = src->begin(); mit != src->end();
1934                      ++mit) {
1935                         uint64_t timestamp =
1936                             m_cycle_timer.timestamp_from_sample_offset((*mit)->timestamp());
1937                         DEBUG_MIDI(string_compose("Queuing outgoing MIDI data for device: "
1938                                                   "%1 sample_offset: %2 timestamp: %3, size: %4\n",
1939                                                   _midiio->get_outputs()[i]->name(),
1940                                                   (*mit)->timestamp(),
1941                                                   timestamp,
1942                                                   (*mit)->size()));
1943                         _midiio->enqueue_output_event(i, timestamp, (*mit)->data(), (*mit)->size());
1944                 }
1945         }
1946 }
1947
1948 void
1949 PortAudioBackend::process_port_connection_changes ()
1950 {
1951         bool connections_changed = false;
1952         bool ports_changed = false;
1953         if (!pthread_mutex_trylock (&_port_callback_mutex)) {
1954                 if (_port_change_flag) {
1955                         ports_changed = true;
1956                         _port_change_flag = false;
1957                 }
1958                 if (!_port_connection_queue.empty ()) {
1959                         connections_changed = true;
1960                 }
1961                 while (!_port_connection_queue.empty ()) {
1962                         PortConnectData *c = _port_connection_queue.back ();
1963                         manager.connect_callback (c->a, c->b, c->c);
1964                         _port_connection_queue.pop_back ();
1965                         delete c;
1966                 }
1967                 pthread_mutex_unlock (&_port_callback_mutex);
1968         }
1969         if (ports_changed) {
1970                 manager.registration_callback();
1971         }
1972         if (connections_changed) {
1973                 manager.graph_order_callback();
1974         }
1975         if (connections_changed || ports_changed) {
1976                 engine.latency_callback(false);
1977                 engine.latency_callback(true);
1978         }
1979 }
1980
1981 /******************************************************************************/
1982
1983 static boost::shared_ptr<PortAudioBackend> _instance;
1984
1985 static boost::shared_ptr<AudioBackend> backend_factory (AudioEngine& e);
1986 static int instantiate (const std::string& arg1, const std::string& /* arg2 */);
1987 static int deinstantiate ();
1988 static bool already_configured ();
1989 static bool available ();
1990
1991 static ARDOUR::AudioBackendInfo _descriptor = {
1992         "PortAudio",
1993         instantiate,
1994         deinstantiate,
1995         backend_factory,
1996         already_configured,
1997         available
1998 };
1999
2000 static boost::shared_ptr<AudioBackend>
2001 backend_factory (AudioEngine& e)
2002 {
2003         if (!_instance) {
2004                 _instance.reset (new PortAudioBackend (e, _descriptor));
2005         }
2006         return _instance;
2007 }
2008
2009 static int
2010 instantiate (const std::string& arg1, const std::string& /* arg2 */)
2011 {
2012         s_instance_name = arg1;
2013         return 0;
2014 }
2015
2016 static int
2017 deinstantiate ()
2018 {
2019         _instance.reset ();
2020         return 0;
2021 }
2022
2023 static bool
2024 already_configured ()
2025 {
2026         return false;
2027 }
2028
2029 static bool
2030 available ()
2031 {
2032         return true;
2033 }
2034
2035 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
2036 {
2037         return &_descriptor;
2038 }
2039
2040
2041 /******************************************************************************/
2042 PamPort::PamPort (PortAudioBackend &b, const std::string& name, PortFlags flags)
2043         : _osx_backend (b)
2044         , _name  (name)
2045         , _flags (flags)
2046 {
2047         _capture_latency_range.min = 0;
2048         _capture_latency_range.max = 0;
2049         _playback_latency_range.min = 0;
2050         _playback_latency_range.max = 0;
2051 }
2052
2053 PamPort::~PamPort () {
2054         disconnect_all ();
2055 }
2056
2057
2058 int PamPort::connect (PamPort *port)
2059 {
2060         if (!port) {
2061                 DEBUG_PORTS("PamPort::connect (): invalid (null) port\n");
2062                 return -1;
2063         }
2064
2065         if (type () != port->type ()) {
2066                 DEBUG_PORTS("PamPort::connect (): wrong port-type\n");
2067                 return -1;
2068         }
2069
2070         if (is_output () && port->is_output ()) {
2071                 DEBUG_PORTS("PamPort::connect (): cannot inter-connect output ports.\n");
2072                 return -1;
2073         }
2074
2075         if (is_input () && port->is_input ()) {
2076                 DEBUG_PORTS("PamPort::connect (): cannot inter-connect input ports.\n");
2077                 return -1;
2078         }
2079
2080         if (this == port) {
2081                 DEBUG_PORTS("PamPort::connect (): cannot self-connect ports.\n");
2082                 return -1;
2083         }
2084
2085         if (is_connected (port)) {
2086 #if 0 // don't bother to warn about this for now. just ignore it
2087                 PBD::error << _("PamPort::connect (): ports are already connected:")
2088                         << " (" << name () << ") -> (" << port->name () << ")"
2089                         << endmsg;
2090 #endif
2091                 return -1;
2092         }
2093
2094         _connect (port, true);
2095         return 0;
2096 }
2097
2098
2099 void PamPort::_connect (PamPort *port, bool callback)
2100 {
2101         _connections.push_back (port);
2102         if (callback) {
2103                 port->_connect (this, false);
2104                 _osx_backend.port_connect_callback (name(),  port->name(), true);
2105         }
2106 }
2107
2108 int PamPort::disconnect (PamPort *port)
2109 {
2110         if (!port) {
2111                 DEBUG_PORTS("PamPort::disconnect (): invalid (null) port\n");
2112                 return -1;
2113         }
2114
2115         if (!is_connected (port)) {
2116                 DEBUG_PORTS(string_compose(
2117                     "PamPort::disconnect (): ports are not connected: (%1) -> (%2)\n",
2118                     name(),
2119                     port->name()));
2120                 return -1;
2121         }
2122         _disconnect (port, true);
2123         return 0;
2124 }
2125
2126 void PamPort::_disconnect (PamPort *port, bool callback)
2127 {
2128         std::vector<PamPort*>::iterator it = std::find (_connections.begin (), _connections.end (), port);
2129
2130         assert (it != _connections.end ());
2131
2132         _connections.erase (it);
2133
2134         if (callback) {
2135                 port->_disconnect (this, false);
2136                 _osx_backend.port_connect_callback (name(),  port->name(), false);
2137         }
2138 }
2139
2140
2141 void PamPort::disconnect_all ()
2142 {
2143         while (!_connections.empty ()) {
2144                 _connections.back ()->_disconnect (this, false);
2145                 _osx_backend.port_connect_callback (name(),  _connections.back ()->name(), false);
2146                 _connections.pop_back ();
2147         }
2148 }
2149
2150 bool
2151 PamPort::is_connected (const PamPort *port) const
2152 {
2153         return std::find (_connections.begin (), _connections.end (), port) != _connections.end ();
2154 }
2155
2156 bool PamPort::is_physically_connected () const
2157 {
2158         for (std::vector<PamPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
2159                 if ((*it)->is_physical ()) {
2160                         return true;
2161                 }
2162         }
2163         return false;
2164 }
2165
2166 /******************************************************************************/
2167
2168 PortAudioPort::PortAudioPort (PortAudioBackend &b, const std::string& name, PortFlags flags)
2169         : PamPort (b, name, flags)
2170 {
2171         memset (_buffer, 0, sizeof (_buffer));
2172 #ifndef PLATFORM_WINDOWS
2173         mlock(_buffer, sizeof (_buffer));
2174 #endif
2175 }
2176
2177 PortAudioPort::~PortAudioPort () { }
2178
2179 void* PortAudioPort::get_buffer (pframes_t n_samples)
2180 {
2181         if (is_input ()) {
2182                 std::vector<PamPort*>::const_iterator it = get_connections ().begin ();
2183                 if (it == get_connections ().end ()) {
2184                         memset (_buffer, 0, n_samples * sizeof (Sample));
2185                 } else {
2186                         PortAudioPort const * source = static_cast<const PortAudioPort*>(*it);
2187                         assert (source && source->is_output ());
2188                         memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
2189                         while (++it != get_connections ().end ()) {
2190                                 source = static_cast<const PortAudioPort*>(*it);
2191                                 assert (source && source->is_output ());
2192                                 Sample* dst = buffer ();
2193                                 const Sample* src = source->const_buffer ();
2194                                 for (uint32_t s = 0; s < n_samples; ++s, ++dst, ++src) {
2195                                         *dst += *src;
2196                                 }
2197                         }
2198                 }
2199         }
2200         return _buffer;
2201 }
2202
2203
2204 PortMidiPort::PortMidiPort (PortAudioBackend &b, const std::string& name, PortFlags flags)
2205         : PamPort (b, name, flags)
2206         , _n_periods (1)
2207         , _bufperiod (0)
2208 {
2209         _buffer[0].clear ();
2210         _buffer[1].clear ();
2211 }
2212
2213 PortMidiPort::~PortMidiPort () { }
2214
2215 struct MidiEventSorter {
2216         bool operator() (const boost::shared_ptr<PortMidiEvent>& a, const boost::shared_ptr<PortMidiEvent>& b) {
2217                 return *a < *b;
2218         }
2219 };
2220
2221 void* PortMidiPort::get_buffer (pframes_t /* nframes */)
2222 {
2223         if (is_input ()) {
2224                 (_buffer[_bufperiod]).clear ();
2225                 for (std::vector<PamPort*>::const_iterator i = get_connections ().begin ();
2226                                 i != get_connections ().end ();
2227                                 ++i) {
2228                         const PortMidiBuffer * src = static_cast<const PortMidiPort*>(*i)->const_buffer ();
2229                         for (PortMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
2230                                 (_buffer[_bufperiod]).push_back (boost::shared_ptr<PortMidiEvent>(new PortMidiEvent (**it)));
2231                         }
2232                 }
2233                 std::sort ((_buffer[_bufperiod]).begin (), (_buffer[_bufperiod]).end (), MidiEventSorter());
2234         }
2235         return &(_buffer[_bufperiod]);
2236 }
2237
2238 PortMidiEvent::PortMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size)
2239         : _size (size)
2240         , _timestamp (timestamp)
2241         , _data (0)
2242 {
2243         if (size > 0) {
2244                 _data = (uint8_t*) malloc (size);
2245                 memcpy (_data, data, size);
2246         }
2247 }
2248
2249 PortMidiEvent::PortMidiEvent (const PortMidiEvent& other)
2250         : _size (other.size ())
2251         , _timestamp (other.timestamp ())
2252         , _data (0)
2253 {
2254         if (other.size () && other.const_data ()) {
2255                 _data = (uint8_t*) malloc (other.size ());
2256                 memcpy (_data, other.const_data (), other.size ());
2257         }
2258 };
2259
2260 PortMidiEvent::~PortMidiEvent () {
2261         free (_data);
2262 };