update reported DSP load for ALSA & Dummy
[ardour.git] / libs / backends / alsa / alsa_audiobackend.cc
1 /*
2  * Copyright (C) 2014 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 #include <sys/mman.h>
22 #include <sys/time.h>
23
24 #include <glibmm.h>
25
26 #include "alsa_audiobackend.h"
27 #include "rt_thread.h"
28
29 #include "pbd/compose.h"
30 #include "pbd/error.h"
31 #include "pbd/file_utils.h"
32 #include "ardour/filesystem_paths.h"
33 #include "ardour/port_manager.h"
34 #include "ardouralsautil/devicelist.h"
35 #include "i18n.h"
36
37 using namespace ARDOUR;
38
39 static std::string s_instance_name;
40 size_t AlsaAudioBackend::_max_buffer_size = 8192;
41 std::vector<std::string> AlsaAudioBackend::_midi_options;
42 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_input_audio_device_status;
43 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_output_audio_device_status;
44 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_duplex_audio_device_status;
45 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_midi_device_status;
46
47 ALSADeviceInfo AlsaAudioBackend::_input_audio_device_info;
48 ALSADeviceInfo AlsaAudioBackend::_output_audio_device_info;
49
50 AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
51         : AudioBackend (e, info)
52         , _pcmi (0)
53         , _run (false)
54         , _active (false)
55         , _freewheel (false)
56         , _freewheeling (false)
57         , _measure_latency (false)
58         , _last_process_start (0)
59         , _input_audio_device("")
60         , _output_audio_device("")
61         , _midi_driver_option(get_standard_device_name(DeviceNone))
62         , _device_reservation(0)
63         , _samplerate (48000)
64         , _samples_per_period (1024)
65         , _periods_per_cycle (2)
66         , _n_inputs (0)
67         , _n_outputs (0)
68         , _systemic_audio_input_latency (0)
69         , _systemic_audio_output_latency (0)
70         , _dsp_load (0)
71         , _processed_samples (0)
72         , _port_change_flag (false)
73 {
74         _instance_name = s_instance_name;
75         pthread_mutex_init (&_port_callback_mutex, 0);
76         _input_audio_device_info.valid = false;
77         _output_audio_device_info.valid = false;
78 }
79
80 AlsaAudioBackend::~AlsaAudioBackend ()
81 {
82         pthread_mutex_destroy (&_port_callback_mutex);
83 }
84
85 /* AUDIOBACKEND API */
86
87 std::string
88 AlsaAudioBackend::name () const
89 {
90         return X_("ALSA");
91 }
92
93 bool
94 AlsaAudioBackend::is_realtime () const
95 {
96         return true;
97 }
98
99 std::vector<AudioBackend::DeviceStatus>
100 AlsaAudioBackend::enumerate_devices () const
101 {
102         _duplex_audio_device_status.clear();
103         std::map<std::string, std::string> devices;
104         get_alsa_audio_device_names(devices);
105         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
106                 if (_input_audio_device == "") _input_audio_device = i->first;
107                 if (_output_audio_device == "") _output_audio_device = i->first;
108                 _duplex_audio_device_status.push_back (DeviceStatus (i->first, true));
109         }
110         return _duplex_audio_device_status;
111 }
112
113 std::vector<AudioBackend::DeviceStatus>
114 AlsaAudioBackend::enumerate_input_devices () const
115 {
116         _input_audio_device_status.clear();
117         std::map<std::string, std::string> devices;
118         get_alsa_audio_device_names(devices, HalfDuplexIn);
119         _input_audio_device_status.push_back (DeviceStatus (get_standard_device_name(DeviceNone), true));
120         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
121                 if (_input_audio_device == "") _input_audio_device = i->first;
122                 _input_audio_device_status.push_back (DeviceStatus (i->first, true));
123         }
124         return _input_audio_device_status;
125 }
126
127 std::vector<AudioBackend::DeviceStatus>
128 AlsaAudioBackend::enumerate_output_devices () const
129 {
130         _output_audio_device_status.clear();
131         std::map<std::string, std::string> devices;
132         get_alsa_audio_device_names(devices, HalfDuplexOut);
133         _output_audio_device_status.push_back (DeviceStatus (get_standard_device_name(DeviceNone), true));
134         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
135                 if (_output_audio_device == "") _output_audio_device = i->first;
136                 _output_audio_device_status.push_back (DeviceStatus (i->first, true));
137         }
138         return _output_audio_device_status;
139 }
140
141 void
142 AlsaAudioBackend::reservation_stdout (std::string d, size_t /* s */)
143 {
144   if (d.substr(0, 19) == "Acquired audio-card") {
145                 _reservation_succeeded = true;
146         }
147 }
148
149 void
150 AlsaAudioBackend::release_device()
151 {
152         _reservation_connection.drop_connections();
153         ARDOUR::SystemExec * tmp = _device_reservation;
154         _device_reservation = 0;
155         delete tmp;
156 }
157
158 bool
159 AlsaAudioBackend::acquire_device(const char* device_name)
160 {
161         /* This is  quick hack, ideally we'll link against libdbus and implement a dbus-listener
162          * that owns the device. here we try to get away by just requesting it and then block it...
163          * (pulseaudio periodically checks anyway)
164          *
165          * dbus-send --session --print-reply --type=method_call --dest=org.freedesktop.ReserveDevice1.Audio2 /org/freedesktop/ReserveDevice1/Audio2 org.freedesktop.ReserveDevice1.RequestRelease int32:4
166          * -> should not return  'boolean false'
167          */
168         int device_number = card_to_num(device_name);
169         if (device_number < 0) return false;
170
171         assert(_device_reservation == 0);
172         _reservation_succeeded = false;
173
174         std::string request_device_exe;
175         if (!PBD::find_file (
176                                 PBD::Searchpath(Glib::build_filename(ARDOUR::ardour_dll_directory(), "ardouralsautil")
177                                         + G_SEARCHPATH_SEPARATOR_S + ARDOUR::ardour_dll_directory()),
178                                 "ardour-request-device", request_device_exe))
179         {
180                 PBD::warning << "ardour-request-device binary was not found..'" << endmsg;
181                 return false;
182         }
183         else
184         {
185                 char **argp;
186                 char tmp[128];
187                 argp=(char**) calloc(5,sizeof(char*));
188                 argp[0] = strdup(request_device_exe.c_str());
189                 argp[1] = strdup("-P");
190                 snprintf(tmp, sizeof(tmp), "%d", getpid());
191                 argp[2] = strdup(tmp);
192                 snprintf(tmp, sizeof(tmp), "Audio%d", device_number);
193                 argp[3] = strdup(tmp);
194                 argp[4] = 0;
195
196                 _device_reservation = new ARDOUR::SystemExec(request_device_exe, argp);
197                 _device_reservation->ReadStdout.connect_same_thread (_reservation_connection, boost::bind (&AlsaAudioBackend::reservation_stdout, this, _1 ,_2));
198                 _device_reservation->Terminated.connect_same_thread (_reservation_connection, boost::bind (&AlsaAudioBackend::release_device, this));
199                 if (_device_reservation->start(0)) {
200                         PBD::warning << _("AlsaAudioBackend: Device Request failed.") << endmsg;
201                         release_device();
202                         return false;
203                 }
204         }
205         // wait to check if reservation suceeded.
206         int timeout = 500; // 5 sec
207         while (_device_reservation && !_reservation_succeeded && --timeout > 0) {
208                 Glib::usleep(10000);
209         }
210         if (timeout == 0 || !_reservation_succeeded) {
211                 PBD::warning << _("AlsaAudioBackend: Device Reservation failed.") << endmsg;
212                 release_device();
213                 return false;
214         }
215         return true;
216 }
217
218 std::vector<float>
219 AlsaAudioBackend::available_sample_rates2 (const std::string& input_device, const std::string& output_device) const
220 {
221         std::vector<float> sr;
222         if (input_device == get_standard_device_name(DeviceNone) && output_device == get_standard_device_name(DeviceNone)) {
223                 return sr;
224         }
225         else if (input_device == get_standard_device_name(DeviceNone)) {
226                 sr = available_sample_rates (output_device);
227         }
228         else if (output_device == get_standard_device_name(DeviceNone)) {
229                 sr = available_sample_rates (input_device);
230         } else {
231                 std::vector<float> sr_in =  available_sample_rates (input_device);
232                 std::vector<float> sr_out = available_sample_rates (output_device);
233                 std::set_intersection (sr_in.begin(), sr_in.end(), sr_out.begin(), sr_out.end(), std::back_inserter(sr));
234         }
235         return sr;
236 }
237
238 std::vector<float>
239 AlsaAudioBackend::available_sample_rates (const std::string& device) const
240 {
241         ALSADeviceInfo *nfo = NULL;
242         std::vector<float> sr;
243         if (device == get_standard_device_name(DeviceNone)) {
244                 return sr;
245         }
246         if (device == _input_audio_device && _input_audio_device_info.valid) {
247                 nfo = &_input_audio_device_info;
248         }
249         else if (device == _output_audio_device && _output_audio_device_info.valid) {
250                 nfo = &_output_audio_device_info;
251         }
252
253         static const float avail_rates [] = { 8000, 22050.0, 24000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 };
254
255         for (size_t i = 0 ; i < sizeof(avail_rates) / sizeof(float); ++i) {
256                 if (!nfo || (avail_rates[i] >= nfo->min_rate && avail_rates[i] <= nfo->max_rate)) {
257                         sr.push_back (avail_rates[i]);
258                 }
259         }
260
261         return sr;
262 }
263
264 std::vector<uint32_t>
265 AlsaAudioBackend::available_buffer_sizes2 (const std::string& input_device, const std::string& output_device) const
266 {
267         std::vector<uint32_t> bs;
268         if (input_device == get_standard_device_name(DeviceNone) && output_device == get_standard_device_name(DeviceNone)) {
269                 return bs;
270         }
271         else if (input_device == get_standard_device_name(DeviceNone)) {
272                 bs = available_buffer_sizes (output_device);
273         }
274         else if (output_device == get_standard_device_name(DeviceNone)) {
275                 bs = available_buffer_sizes (input_device);
276         } else {
277                 std::vector<uint32_t> bs_in =  available_buffer_sizes (input_device);
278                 std::vector<uint32_t> bs_out = available_buffer_sizes (output_device);
279                 std::set_intersection (bs_in.begin(), bs_in.end(), bs_out.begin(), bs_out.end(), std::back_inserter(bs));
280         }
281         return bs;
282 }
283
284 std::vector<uint32_t>
285 AlsaAudioBackend::available_buffer_sizes (const std::string& device) const
286 {
287         ALSADeviceInfo *nfo = NULL;
288         std::vector<uint32_t> bs;
289         if (device == get_standard_device_name(DeviceNone)) {
290                 return bs;
291         }
292         if (device == _input_audio_device && _input_audio_device_info.valid) {
293                 nfo = &_input_audio_device_info;
294         }
295         else if (device == _output_audio_device && _output_audio_device_info.valid) {
296                 nfo = &_output_audio_device_info;
297         }
298
299         static const unsigned long avail_sizes [] = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
300
301         for (size_t i = 0 ; i < sizeof(avail_sizes) / sizeof(unsigned long); ++i) {
302                 if (!nfo || (avail_sizes[i] >= nfo->min_size && avail_sizes[i] <= nfo->max_size)) {
303                         bs.push_back (avail_sizes[i]);
304                 }
305         }
306         return bs;
307 }
308
309 uint32_t
310 AlsaAudioBackend::available_input_channel_count (const std::string& device) const
311 {
312         if (device == get_standard_device_name(DeviceNone)) {
313                 return 0;
314         }
315         if (device == _input_audio_device && _input_audio_device_info.valid) {
316                 return _input_audio_device_info.max_channels;
317         }
318         return 128;
319 }
320
321 uint32_t
322 AlsaAudioBackend::available_output_channel_count (const std::string& device) const
323 {
324         if (device == get_standard_device_name(DeviceNone)) {
325                 return 0;
326         }
327         if (device == _output_audio_device && _output_audio_device_info.valid) {
328                 return _output_audio_device_info.max_channels;
329         }
330         return 128;
331 }
332
333 bool
334 AlsaAudioBackend::can_change_sample_rate_when_running () const
335 {
336         return false;
337 }
338
339 bool
340 AlsaAudioBackend::can_change_buffer_size_when_running () const
341 {
342         return false; // why not? :)
343 }
344
345 int
346 AlsaAudioBackend::set_input_device_name (const std::string& d)
347 {
348         if (_input_audio_device == d) {
349                 return 0;
350         }
351         _input_audio_device = d;
352
353         if (d == get_standard_device_name(DeviceNone)) {
354                 _input_audio_device_info.valid = false;
355                 return 0;
356         }
357         std::string alsa_device;
358         std::map<std::string, std::string> devices;
359
360         get_alsa_audio_device_names(devices, HalfDuplexIn);
361         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
362                 if (i->first == d) {
363                         alsa_device = i->second;
364                         break;
365                 }
366         }
367         if (alsa_device == "") {
368                 _input_audio_device_info.valid = false;
369                 return 1;
370         }
371         /* device will be busy once used, hence cache the parameters */
372         /* return */ get_alsa_device_parameters (alsa_device.c_str(), true, &_input_audio_device_info);
373         return 0;
374 }
375
376 int
377 AlsaAudioBackend::set_output_device_name (const std::string& d)
378 {
379         if (_output_audio_device == d) {
380                 return 0;
381         }
382
383         _output_audio_device = d;
384
385         if (d == get_standard_device_name(DeviceNone)) {
386                 _output_audio_device_info.valid = false;
387                 return 0;
388         }
389         std::string alsa_device;
390         std::map<std::string, std::string> devices;
391
392         get_alsa_audio_device_names(devices, HalfDuplexOut);
393         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
394                 if (i->first == d) {
395                         alsa_device = i->second;
396                         break;
397                 }
398         }
399         if (alsa_device == "") {
400                 _output_audio_device_info.valid = false;
401                 return 1;
402         }
403         /* return */ get_alsa_device_parameters (alsa_device.c_str(), true, &_output_audio_device_info);
404         return 0;
405 }
406
407 int
408 AlsaAudioBackend::set_device_name (const std::string& d)
409 {
410         int rv = 0;
411         rv |= set_input_device_name (d);
412         rv |= set_output_device_name (d);
413         return rv;
414 }
415
416 int
417 AlsaAudioBackend::set_sample_rate (float sr)
418 {
419         if (sr <= 0) { return -1; }
420         _samplerate = sr;
421         engine.sample_rate_change (sr);
422         return 0;
423 }
424
425 int
426 AlsaAudioBackend::set_buffer_size (uint32_t bs)
427 {
428         if (bs <= 0 || bs >= _max_buffer_size) {
429                 return -1;
430         }
431         if (_run) {
432                 return -1;
433         }
434         _samples_per_period = bs;
435         engine.buffer_size_change (bs);
436         return 0;
437 }
438
439 int
440 AlsaAudioBackend::set_interleaved (bool yn)
441 {
442         if (!yn) { return 0; }
443         return -1;
444 }
445
446 int
447 AlsaAudioBackend::set_input_channels (uint32_t cc)
448 {
449         _n_inputs = cc;
450         return 0;
451 }
452
453 int
454 AlsaAudioBackend::set_output_channels (uint32_t cc)
455 {
456         _n_outputs = cc;
457         return 0;
458 }
459
460 int
461 AlsaAudioBackend::set_systemic_input_latency (uint32_t sl)
462 {
463         _systemic_audio_input_latency = sl;
464         return 0;
465 }
466
467 int
468 AlsaAudioBackend::set_systemic_output_latency (uint32_t sl)
469 {
470         _systemic_audio_output_latency = sl;
471         return 0;
472 }
473
474 int
475 AlsaAudioBackend::set_systemic_midi_input_latency (std::string const device, uint32_t sl)
476 {
477         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
478         if (!nfo) return -1;
479         nfo->systemic_input_latency = sl;
480         return 0;
481 }
482
483 int
484 AlsaAudioBackend::set_systemic_midi_output_latency (std::string const device, uint32_t sl)
485 {
486         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
487         if (!nfo) return -1;
488         nfo->systemic_output_latency = sl;
489         return 0;
490 }
491
492 /* Retrieving parameters */
493 std::string
494 AlsaAudioBackend::device_name () const
495 {
496         if (_input_audio_device != get_standard_device_name(DeviceNone)) {
497                 return _input_audio_device;
498         }
499         if (_output_audio_device != get_standard_device_name(DeviceNone)) {
500                 return _output_audio_device;
501         }
502         return "";
503 }
504
505 std::string
506 AlsaAudioBackend::input_device_name () const
507 {
508         return _input_audio_device;
509 }
510
511 std::string
512 AlsaAudioBackend::output_device_name () const
513 {
514         return _output_audio_device;
515 }
516
517 float
518 AlsaAudioBackend::sample_rate () const
519 {
520         return _samplerate;
521 }
522
523 uint32_t
524 AlsaAudioBackend::buffer_size () const
525 {
526         return _samples_per_period;
527 }
528
529 bool
530 AlsaAudioBackend::interleaved () const
531 {
532         return false;
533 }
534
535 uint32_t
536 AlsaAudioBackend::input_channels () const
537 {
538         return _n_inputs;
539 }
540
541 uint32_t
542 AlsaAudioBackend::output_channels () const
543 {
544         return _n_outputs;
545 }
546
547 uint32_t
548 AlsaAudioBackend::systemic_input_latency () const
549 {
550         return _systemic_audio_input_latency;
551 }
552
553 uint32_t
554 AlsaAudioBackend::systemic_output_latency () const
555 {
556         return _systemic_audio_output_latency;
557 }
558
559 uint32_t
560 AlsaAudioBackend::systemic_midi_input_latency (std::string const device) const
561 {
562         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
563         if (!nfo) return 0;
564         return nfo->systemic_input_latency;
565 }
566
567 uint32_t
568 AlsaAudioBackend::systemic_midi_output_latency (std::string const device) const
569 {
570         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
571         if (!nfo) return 0;
572         return nfo->systemic_output_latency;
573 }
574
575 /* MIDI */
576 struct AlsaAudioBackend::AlsaMidiDeviceInfo *
577 AlsaAudioBackend::midi_device_info(std::string const name) const {
578         for (std::map<std::string, struct AlsaMidiDeviceInfo*>::const_iterator i = _midi_devices.begin (); i != _midi_devices.end(); ++i) {
579                 if (i->first == name) {
580                         return (i->second);
581                 }
582         }
583
584         assert(_midi_driver_option != get_standard_device_name(DeviceNone));
585
586         std::map<std::string, std::string> devices;
587         if (_midi_driver_option == _("ALSA raw devices")) {
588                 get_alsa_rawmidi_device_names(devices);
589         } else {
590                 get_alsa_sequencer_names (devices);
591         }
592
593         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
594                 if (i->first == name) {
595                         _midi_devices[name] = new AlsaMidiDeviceInfo();
596                         return _midi_devices[name];
597                 }
598         }
599         return 0;
600 }
601
602 std::vector<std::string>
603 AlsaAudioBackend::enumerate_midi_options () const
604 {
605         if (_midi_options.empty()) {
606                 _midi_options.push_back (_("ALSA raw devices"));
607                 _midi_options.push_back (_("ALSA sequencer"));
608                 _midi_options.push_back (get_standard_device_name(DeviceNone));
609         }
610         return _midi_options;
611 }
612
613 std::vector<AudioBackend::DeviceStatus>
614 AlsaAudioBackend::enumerate_midi_devices () const
615 {
616         _midi_device_status.clear();
617         std::map<std::string, std::string> devices;
618
619         if (_midi_driver_option == _("ALSA raw devices")) {
620                 get_alsa_rawmidi_device_names (devices);
621         }
622         else if (_midi_driver_option == _("ALSA sequencer")) {
623                 get_alsa_sequencer_names (devices);
624         }
625
626         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
627                 _midi_device_status.push_back (DeviceStatus (i->first, true));
628         }
629         return _midi_device_status;
630 }
631
632 int
633 AlsaAudioBackend::set_midi_option (const std::string& opt)
634 {
635         if (opt != get_standard_device_name(DeviceNone) && opt != _("ALSA raw devices") && opt != _("ALSA sequencer")) {
636                 return -1;
637         }
638         _midi_driver_option = opt;
639         return 0;
640 }
641
642 std::string
643 AlsaAudioBackend::midi_option () const
644 {
645         return _midi_driver_option;
646 }
647
648 int
649 AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable)
650 {
651         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
652         if (!nfo) return -1;
653         nfo->enabled = enable;
654         return 0;
655 }
656
657 bool
658 AlsaAudioBackend::midi_device_enabled (std::string const device) const
659 {
660         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
661         if (!nfo) return false;
662         return nfo->enabled;
663 }
664
665 /* State Control */
666
667 static void * pthread_process (void *arg)
668 {
669         AlsaAudioBackend *d = static_cast<AlsaAudioBackend *>(arg);
670         d->main_process_thread ();
671         pthread_exit (0);
672         return 0;
673 }
674
675 int
676 AlsaAudioBackend::_start (bool for_latency_measurement)
677 {
678         if (!_active && _run) {
679                 // recover from 'halted', reap threads
680                 stop();
681         }
682
683         if (_active || _run) {
684                 PBD::error << _("AlsaAudioBackend: already active.") << endmsg;
685                 return -1;
686         }
687
688         if (_ports.size()) {
689                 PBD::warning << _("AlsaAudioBackend: recovering from unclean shutdown, port registry is not empty.") << endmsg;
690                 _system_inputs.clear();
691                 _system_outputs.clear();
692                 _system_midi_in.clear();
693                 _system_midi_out.clear();
694                 _ports.clear();
695         }
696
697         /* reset internal state */
698         _dsp_load = 0;
699         _freewheeling = false;
700         _freewheel = false;
701         _last_process_start = 0;
702
703         release_device();
704
705         assert(_rmidi_in.size() == 0);
706         assert(_rmidi_out.size() == 0);
707         assert(_pcmi == 0);
708
709         int duplex = 0;
710         std::string audio_device;
711         std::string alsa_device;
712         std::map<std::string, std::string> devices;
713
714         if (_input_audio_device == get_standard_device_name(DeviceNone) && _output_audio_device == get_standard_device_name(DeviceNone)) {
715                 PBD::error << _("AlsaAudioBackend: At least one of input or output device needs to be set.");
716                 return -1;
717         }
718
719         if (_input_audio_device != _output_audio_device) {
720                 if (_input_audio_device != get_standard_device_name(DeviceNone) && _output_audio_device != get_standard_device_name(DeviceNone)) {
721                         PBD::error << _("AlsaAudioBackend: Cannot use two different devices.");
722                         return -1;
723                 }
724                 if (_input_audio_device != get_standard_device_name(DeviceNone)) {
725                         get_alsa_audio_device_names(devices, HalfDuplexIn);
726                         audio_device = _input_audio_device;
727                         duplex = 1;
728                 } else {
729                         get_alsa_audio_device_names(devices, HalfDuplexOut);
730                         audio_device = _output_audio_device;
731                         duplex = 2;
732                 }
733         } else {
734                 get_alsa_audio_device_names(devices);
735                 audio_device = _input_audio_device;
736                 duplex = 3;
737         }
738
739         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
740                 if (i->first == audio_device) {
741                         alsa_device = i->second;
742                         break;
743                 }
744         }
745         if (alsa_device == "") {
746                 PBD::error << _("AlsaAudioBackend: Cannot find configured device. Is it still connected?");
747                 return -1;
748         }
749
750         acquire_device(alsa_device.c_str());
751         _pcmi = new Alsa_pcmi (
752                         (duplex & 2) ? alsa_device.c_str() : NULL,
753                         (duplex & 1) ? alsa_device.c_str() : NULL,
754                         0, _samplerate, _samples_per_period, _periods_per_cycle, 0);
755         switch (_pcmi->state ()) {
756                 case 0: /* OK */ break;
757                 case -1: PBD::error << _("AlsaAudioBackend: failed to open device.") << endmsg; break;
758                 case -2: PBD::error << _("AlsaAudioBackend: failed to allocate parameters.") << endmsg; break;
759                 case -3: PBD::error << _("AlsaAudioBackend: cannot set requested sample rate.") << endmsg; break;
760                 case -4: PBD::error << _("AlsaAudioBackend: cannot set requested period size.") << endmsg; break;
761                 case -5: PBD::error << _("AlsaAudioBackend: cannot set requested number of periods.") << endmsg; break;
762                 case -6: PBD::error << _("AlsaAudioBackend: unsupported sample format.") << endmsg; break;
763                 default: PBD::error << _("AlsaAudioBackend: initialization failed.") << endmsg; break;
764         }
765         if (_pcmi->state ()) {
766                 delete _pcmi; _pcmi = 0;
767                 release_device();
768                 return -1;
769         }
770
771 #ifndef NDEBUG
772         _pcmi->printinfo ();
773 #endif
774
775         if (_n_outputs != _pcmi->nplay ()) {
776                 if (_n_outputs == 0) {
777                  _n_outputs = _pcmi->nplay ();
778                 } else {
779                  _n_outputs = std::min (_n_outputs, _pcmi->nplay ());
780                 }
781                 PBD::warning << _("AlsaAudioBackend: adjusted output channel count to match device.") << endmsg;
782         }
783
784         if (_n_inputs != _pcmi->ncapt ()) {
785                 if (_n_inputs == 0) {
786                  _n_inputs = _pcmi->ncapt ();
787                 } else {
788                  _n_inputs = std::min (_n_inputs, _pcmi->ncapt ());
789                 }
790                 PBD::warning << _("AlsaAudioBackend: adjusted input channel count to match device.") << endmsg;
791         }
792
793         if (_pcmi->fsize() != _samples_per_period) {
794                 _samples_per_period = _pcmi->fsize();
795                 PBD::warning << _("AlsaAudioBackend: samples per period does not match.") << endmsg;
796         }
797
798         if (_pcmi->fsamp() != _samplerate) {
799                 _samplerate = _pcmi->fsamp();
800                 engine.sample_rate_change (_samplerate);
801                 PBD::warning << _("AlsaAudioBackend: sample rate does not match.") << endmsg;
802         }
803
804         _measure_latency = for_latency_measurement;
805
806         register_system_midi_ports();
807
808         if (register_system_audio_ports()) {
809                 PBD::error << _("AlsaAudioBackend: failed to register system ports.") << endmsg;
810                 delete _pcmi; _pcmi = 0;
811                 release_device();
812                 return -1;
813         }
814
815         engine.sample_rate_change (_samplerate);
816         engine.buffer_size_change (_samples_per_period);
817
818         if (engine.reestablish_ports ()) {
819                 PBD::error << _("AlsaAudioBackend: Could not re-establish ports.") << endmsg;
820                 delete _pcmi; _pcmi = 0;
821                 release_device();
822                 return -1;
823         }
824
825         engine.reconnect_ports ();
826         _run = true;
827         _port_change_flag = false;
828
829         if (_realtime_pthread_create (SCHED_FIFO, -20, 100000,
830                                 &_main_thread, pthread_process, this))
831         {
832                 if (pthread_create (&_main_thread, NULL, pthread_process, this))
833                 {
834                         PBD::error << _("AlsaAudioBackend: failed to create process thread.") << endmsg;
835                         delete _pcmi; _pcmi = 0;
836                         release_device();
837                         _run = false;
838                         return -1;
839                 } else {
840                         PBD::warning << _("AlsaAudioBackend: cannot acquire realtime permissions.") << endmsg;
841                 }
842         }
843
844         int timeout = 5000;
845         while (!_active && --timeout > 0) { Glib::usleep (1000); }
846
847         if (timeout == 0 || !_active) {
848                 PBD::error << _("AlsaAudioBackend: failed to start process thread.") << endmsg;
849                 delete _pcmi; _pcmi = 0;
850                 release_device();
851                 _run = false;
852                 return -1;
853         }
854
855         return 0;
856 }
857
858 int
859 AlsaAudioBackend::stop ()
860 {
861         void *status;
862         if (!_run) {
863                 return 0;
864         }
865
866         _run = false;
867         if (pthread_join (_main_thread, &status)) {
868                 PBD::error << _("AlsaAudioBackend: failed to terminate.") << endmsg;
869                 return -1;
870         }
871
872         while (!_rmidi_out.empty ()) {
873                 AlsaMidiIO *m = _rmidi_out.back ();
874                 m->stop();
875                 _rmidi_out.pop_back ();
876                 delete m;
877         }
878         while (!_rmidi_in.empty ()) {
879                 AlsaMidiIO *m = _rmidi_in.back ();
880                 m->stop();
881                 _rmidi_in.pop_back ();
882                 delete m;
883         }
884
885         unregister_ports();
886         delete _pcmi; _pcmi = 0;
887         release_device();
888
889         return (_active == false) ? 0 : -1;
890 }
891
892 int
893 AlsaAudioBackend::freewheel (bool onoff)
894 {
895         _freewheeling = onoff;
896         return 0;
897 }
898
899 float
900 AlsaAudioBackend::dsp_load () const
901 {
902         return 100.f * _dsp_load;
903 }
904
905 size_t
906 AlsaAudioBackend::raw_buffer_size (DataType t)
907 {
908         switch (t) {
909                 case DataType::AUDIO:
910                         return _samples_per_period * sizeof(Sample);
911                 case DataType::MIDI:
912                         return _max_buffer_size; // XXX not really limited
913         }
914         return 0;
915 }
916
917 /* Process time */
918 framepos_t
919 AlsaAudioBackend::sample_time ()
920 {
921         return _processed_samples;
922 }
923
924 framepos_t
925 AlsaAudioBackend::sample_time_at_cycle_start ()
926 {
927         return _processed_samples;
928 }
929
930 pframes_t
931 AlsaAudioBackend::samples_since_cycle_start ()
932 {
933         if (!_active || !_run || _freewheeling || _freewheel) {
934                 return 0;
935         }
936         if (_last_process_start == 0) {
937                 return 0;
938         }
939
940         const int64_t elapsed_time_us = g_get_monotonic_time() - _last_process_start;
941         return std::max((pframes_t)0, (pframes_t)rint(1e-6 * elapsed_time_us * _samplerate));
942 }
943
944
945 void *
946 AlsaAudioBackend::alsa_process_thread (void *arg)
947 {
948         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
949         boost::function<void ()> f = td->f;
950         delete td;
951         f ();
952         return 0;
953 }
954
955 int
956 AlsaAudioBackend::create_process_thread (boost::function<void()> func)
957 {
958         pthread_t thread_id;
959         pthread_attr_t attr;
960         size_t stacksize = 100000;
961
962         ThreadData* td = new ThreadData (this, func, stacksize);
963
964         if (_realtime_pthread_create (SCHED_FIFO, -21, stacksize,
965                                 &thread_id, alsa_process_thread, td)) {
966                 pthread_attr_init (&attr);
967                 pthread_attr_setstacksize (&attr, stacksize);
968                 if (pthread_create (&thread_id, &attr, alsa_process_thread, td)) {
969                         PBD::error << _("AudioEngine: cannot create process thread.") << endmsg;
970                         pthread_attr_destroy (&attr);
971                         return -1;
972                 }
973                 pthread_attr_destroy (&attr);
974         }
975
976         _threads.push_back (thread_id);
977         return 0;
978 }
979
980 int
981 AlsaAudioBackend::join_process_threads ()
982 {
983         int rv = 0;
984
985         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
986         {
987                 void *status;
988                 if (pthread_join (*i, &status)) {
989                         PBD::error << _("AudioEngine: cannot terminate process thread.") << endmsg;
990                         rv -= 1;
991                 }
992         }
993         _threads.clear ();
994         return rv;
995 }
996
997 bool
998 AlsaAudioBackend::in_process_thread ()
999 {
1000         if (pthread_equal (_main_thread, pthread_self()) != 0) {
1001                 return true;
1002         }
1003
1004         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
1005         {
1006                 if (pthread_equal (*i, pthread_self ()) != 0) {
1007                         return true;
1008                 }
1009         }
1010         return false;
1011 }
1012
1013 uint32_t
1014 AlsaAudioBackend::process_thread_count ()
1015 {
1016         return _threads.size ();
1017 }
1018
1019 void
1020 AlsaAudioBackend::update_latencies ()
1021 {
1022         // trigger latency callback in RT thread (locked graph)
1023         port_connect_add_remove_callback();
1024 }
1025
1026 /* PORTENGINE API */
1027
1028 void*
1029 AlsaAudioBackend::private_handle () const
1030 {
1031         return NULL;
1032 }
1033
1034 const std::string&
1035 AlsaAudioBackend::my_name () const
1036 {
1037         return _instance_name;
1038 }
1039
1040 bool
1041 AlsaAudioBackend::available () const
1042 {
1043         return _run && _active;
1044 }
1045
1046 uint32_t
1047 AlsaAudioBackend::port_name_size () const
1048 {
1049         return 256;
1050 }
1051
1052 int
1053 AlsaAudioBackend::set_port_name (PortEngine::PortHandle port, const std::string& name)
1054 {
1055         if (!valid_port (port)) {
1056                 PBD::error << _("AlsaBackend::set_port_name: Invalid Port(s)") << endmsg;
1057                 return -1;
1058         }
1059         return static_cast<AlsaPort*>(port)->set_name (_instance_name + ":" + name);
1060 }
1061
1062 std::string
1063 AlsaAudioBackend::get_port_name (PortEngine::PortHandle port) const
1064 {
1065         if (!valid_port (port)) {
1066                 PBD::error << _("AlsaBackend::get_port_name: Invalid Port(s)") << endmsg;
1067                 return std::string ();
1068         }
1069         return static_cast<AlsaPort*>(port)->name ();
1070 }
1071
1072 PortEngine::PortHandle
1073 AlsaAudioBackend::get_port_by_name (const std::string& name) const
1074 {
1075         PortHandle port = (PortHandle) find_port (name);
1076         return port;
1077 }
1078
1079 int
1080 AlsaAudioBackend::get_ports (
1081                 const std::string& port_name_pattern,
1082                 DataType type, PortFlags flags,
1083                 std::vector<std::string>& port_names) const
1084 {
1085         int rv = 0;
1086         regex_t port_regex;
1087         bool use_regexp = false;
1088         if (port_name_pattern.size () > 0) {
1089                 if (!regcomp (&port_regex, port_name_pattern.c_str (), REG_EXTENDED|REG_NOSUB)) {
1090                         use_regexp = true;
1091                 }
1092         }
1093         for (size_t i = 0; i < _ports.size (); ++i) {
1094                 AlsaPort* port = _ports[i];
1095                 if ((port->type () == type) && flags == (port->flags () & flags)) {
1096                         if (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) {
1097                                 port_names.push_back (port->name ());
1098                                 ++rv;
1099                         }
1100                 }
1101         }
1102         if (use_regexp) {
1103                 regfree (&port_regex);
1104         }
1105         return rv;
1106 }
1107
1108 DataType
1109 AlsaAudioBackend::port_data_type (PortEngine::PortHandle port) const
1110 {
1111         if (!valid_port (port)) {
1112                 return DataType::NIL;
1113         }
1114         return static_cast<AlsaPort*>(port)->type ();
1115 }
1116
1117 PortEngine::PortHandle
1118 AlsaAudioBackend::register_port (
1119                 const std::string& name,
1120                 ARDOUR::DataType type,
1121                 ARDOUR::PortFlags flags)
1122 {
1123         if (name.size () == 0) { return 0; }
1124         if (flags & IsPhysical) { return 0; }
1125         return add_port (_instance_name + ":" + name, type, flags);
1126 }
1127
1128 PortEngine::PortHandle
1129 AlsaAudioBackend::add_port (
1130                 const std::string& name,
1131                 ARDOUR::DataType type,
1132                 ARDOUR::PortFlags flags)
1133 {
1134         assert(name.size ());
1135         if (find_port (name)) {
1136                 PBD::error << _("AlsaBackend::register_port: Port already exists:")
1137                                 << " (" << name << ")" << endmsg;
1138                 return 0;
1139         }
1140         AlsaPort* port = NULL;
1141         switch (type) {
1142                 case DataType::AUDIO:
1143                         port = new AlsaAudioPort (*this, name, flags);
1144                         break;
1145                 case DataType::MIDI:
1146                         port = new AlsaMidiPort (*this, name, flags);
1147                         break;
1148                 default:
1149                         PBD::error << _("AlsaBackend::register_port: Invalid Data Type.") << endmsg;
1150                         return 0;
1151         }
1152
1153         _ports.push_back (port);
1154
1155         return port;
1156 }
1157
1158 void
1159 AlsaAudioBackend::unregister_port (PortEngine::PortHandle port_handle)
1160 {
1161         if (!_run) {
1162                 return;
1163         }
1164         AlsaPort* port = static_cast<AlsaPort*>(port_handle);
1165         std::vector<AlsaPort*>::iterator i = std::find (_ports.begin (), _ports.end (), static_cast<AlsaPort*>(port_handle));
1166         if (i == _ports.end ()) {
1167                 PBD::error << _("AlsaBackend::unregister_port: Failed to find port") << endmsg;
1168                 return;
1169         }
1170         disconnect_all(port_handle);
1171         _ports.erase (i);
1172         delete port;
1173 }
1174
1175 int
1176 AlsaAudioBackend::register_system_audio_ports()
1177 {
1178         LatencyRange lr;
1179
1180         const int a_ins = _n_inputs;
1181         const int a_out = _n_outputs;
1182
1183         /* audio ports */
1184         lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_input_latency);
1185         for (int i = 1; i <= a_ins; ++i) {
1186                 char tmp[64];
1187                 snprintf(tmp, sizeof(tmp), "system:capture_%d", i);
1188                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
1189                 if (!p) return -1;
1190                 set_latency_range (p, false, lr);
1191                 _system_inputs.push_back(static_cast<AlsaPort*>(p));
1192         }
1193
1194         lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_output_latency);
1195         for (int i = 1; i <= a_out; ++i) {
1196                 char tmp[64];
1197                 snprintf(tmp, sizeof(tmp), "system:playback_%d", i);
1198                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
1199                 if (!p) return -1;
1200                 set_latency_range (p, true, lr);
1201                 _system_outputs.push_back(static_cast<AlsaPort*>(p));
1202         }
1203         return 0;
1204 }
1205
1206 int
1207 AlsaAudioBackend::register_system_midi_ports()
1208 {
1209         std::map<std::string, std::string> devices;
1210         int midi_ins = 0;
1211         int midi_outs = 0;
1212
1213         if (_midi_driver_option == get_standard_device_name(DeviceNone)) {
1214                 return 0;
1215         } else if (_midi_driver_option == _("ALSA raw devices")) {
1216                 get_alsa_rawmidi_device_names(devices);
1217         } else {
1218                 get_alsa_sequencer_names (devices);
1219         }
1220
1221         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
1222                 struct AlsaMidiDeviceInfo * nfo = midi_device_info(i->first);
1223                 if (!nfo) continue;
1224                 if (!nfo->enabled) continue;
1225
1226                 AlsaMidiOut *mout;
1227                 if (_midi_driver_option == _("ALSA raw devices")) {
1228                         mout = new AlsaRawMidiOut (i->second.c_str());
1229                 } else {
1230                         mout = new AlsaSeqMidiOut (i->second.c_str());
1231                 }
1232
1233                 if (mout->state ()) {
1234                         PBD::warning << string_compose (
1235                                         _("AlsaMidiOut: failed to open midi device '%1'."), i->second)
1236                                 << endmsg;
1237                         delete mout;
1238                 } else {
1239                         mout->setup_timing(_samples_per_period, _samplerate);
1240                         mout->sync_time (g_get_monotonic_time());
1241                         if (mout->start ()) {
1242                                 PBD::warning << string_compose (
1243                                                 _("AlsaMidiOut: failed to start midi device '%1'."), i->second)
1244                                         << endmsg;
1245                                 delete mout;
1246                         } else {
1247                                 char tmp[64];
1248                                 snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++midi_ins);
1249                                 PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
1250                                 if (!p) {
1251                                         mout->stop();
1252                                         delete mout;
1253                                 }
1254                                 LatencyRange lr;
1255                                 lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency);
1256                                 set_latency_range (p, false, lr);
1257                                 static_cast<AlsaMidiPort*>(p)->set_n_periods(2);
1258                                 _system_midi_out.push_back(static_cast<AlsaPort*>(p));
1259                                 _rmidi_out.push_back (mout);
1260                         }
1261                 }
1262
1263                 AlsaMidiIn *midin;
1264                 if (_midi_driver_option == _("ALSA raw devices")) {
1265                         midin = new AlsaRawMidiIn (i->second.c_str());
1266                 } else {
1267                         midin = new AlsaSeqMidiIn (i->second.c_str());
1268                 }
1269
1270                 if (midin->state ()) {
1271                         PBD::warning << string_compose (
1272                                         _("AlsaMidiIn: failed to open midi device '%1'."), i->second)
1273                                 << endmsg;
1274                         delete midin;
1275                 } else {
1276                         midin->setup_timing(_samples_per_period, _samplerate);
1277                         midin->sync_time (g_get_monotonic_time());
1278                         if (midin->start ()) {
1279                                 PBD::warning << string_compose (
1280                                                 _("AlsaMidiIn: failed to start midi device '%1'."), i->second)
1281                                         << endmsg;
1282                                 delete midin;
1283                         } else {
1284                                 char tmp[64];
1285                                 snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++midi_outs);
1286                                 PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
1287                                 if (!p) {
1288                                         midin->stop();
1289                                         delete midin;
1290                                         continue;
1291                                 }
1292                                 LatencyRange lr;
1293                                 lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_input_latency);
1294                                 set_latency_range (p, false, lr);
1295                                 _system_midi_in.push_back(static_cast<AlsaPort*>(p));
1296                                 _rmidi_in.push_back (midin);
1297                         }
1298                 }
1299         }
1300         return 0;
1301 }
1302
1303 void
1304 AlsaAudioBackend::unregister_ports (bool system_only)
1305 {
1306         size_t i = 0;
1307         _system_inputs.clear();
1308         _system_outputs.clear();
1309         _system_midi_in.clear();
1310         _system_midi_out.clear();
1311         while (i <  _ports.size ()) {
1312                 AlsaPort* port = _ports[i];
1313                 if (! system_only || (port->is_physical () && port->is_terminal ())) {
1314                         port->disconnect_all ();
1315                         delete port;
1316                         _ports.erase (_ports.begin() + i);
1317                 } else {
1318                         ++i;
1319                 }
1320         }
1321 }
1322
1323 int
1324 AlsaAudioBackend::connect (const std::string& src, const std::string& dst)
1325 {
1326         AlsaPort* src_port = find_port (src);
1327         AlsaPort* dst_port = find_port (dst);
1328
1329         if (!src_port) {
1330                 PBD::error << _("AlsaBackend::connect: Invalid Source port:")
1331                                 << " (" << src <<")" << endmsg;
1332                 return -1;
1333         }
1334         if (!dst_port) {
1335                 PBD::error << _("AlsaBackend::connect: Invalid Destination port:")
1336                         << " (" << dst <<")" << endmsg;
1337                 return -1;
1338         }
1339         return src_port->connect (dst_port);
1340 }
1341
1342 int
1343 AlsaAudioBackend::disconnect (const std::string& src, const std::string& dst)
1344 {
1345         AlsaPort* src_port = find_port (src);
1346         AlsaPort* dst_port = find_port (dst);
1347
1348         if (!src_port || !dst_port) {
1349                 PBD::error << _("AlsaBackend::disconnect: Invalid Port(s)") << endmsg;
1350                 return -1;
1351         }
1352         return src_port->disconnect (dst_port);
1353 }
1354
1355 int
1356 AlsaAudioBackend::connect (PortEngine::PortHandle src, const std::string& dst)
1357 {
1358         AlsaPort* dst_port = find_port (dst);
1359         if (!valid_port (src)) {
1360                 PBD::error << _("AlsaBackend::connect: Invalid Source Port Handle") << endmsg;
1361                 return -1;
1362         }
1363         if (!dst_port) {
1364                 PBD::error << _("AlsaBackend::connect: Invalid Destination Port")
1365                         << " (" << dst << ")" << endmsg;
1366                 return -1;
1367         }
1368         return static_cast<AlsaPort*>(src)->connect (dst_port);
1369 }
1370
1371 int
1372 AlsaAudioBackend::disconnect (PortEngine::PortHandle src, const std::string& dst)
1373 {
1374         AlsaPort* dst_port = find_port (dst);
1375         if (!valid_port (src) || !dst_port) {
1376                 PBD::error << _("AlsaBackend::disconnect: Invalid Port(s)") << endmsg;
1377                 return -1;
1378         }
1379         return static_cast<AlsaPort*>(src)->disconnect (dst_port);
1380 }
1381
1382 int
1383 AlsaAudioBackend::disconnect_all (PortEngine::PortHandle port)
1384 {
1385         if (!valid_port (port)) {
1386                 PBD::error << _("AlsaBackend::disconnect_all: Invalid Port") << endmsg;
1387                 return -1;
1388         }
1389         static_cast<AlsaPort*>(port)->disconnect_all ();
1390         return 0;
1391 }
1392
1393 bool
1394 AlsaAudioBackend::connected (PortEngine::PortHandle port, bool /* process_callback_safe*/)
1395 {
1396         if (!valid_port (port)) {
1397                 PBD::error << _("AlsaBackend::disconnect_all: Invalid Port") << endmsg;
1398                 return false;
1399         }
1400         return static_cast<AlsaPort*>(port)->is_connected ();
1401 }
1402
1403 bool
1404 AlsaAudioBackend::connected_to (PortEngine::PortHandle src, const std::string& dst, bool /*process_callback_safe*/)
1405 {
1406         AlsaPort* dst_port = find_port (dst);
1407         if (!valid_port (src) || !dst_port) {
1408                 PBD::error << _("AlsaBackend::connected_to: Invalid Port") << endmsg;
1409                 return false;
1410         }
1411         return static_cast<AlsaPort*>(src)->is_connected (dst_port);
1412 }
1413
1414 bool
1415 AlsaAudioBackend::physically_connected (PortEngine::PortHandle port, bool /*process_callback_safe*/)
1416 {
1417         if (!valid_port (port)) {
1418                 PBD::error << _("AlsaBackend::physically_connected: Invalid Port") << endmsg;
1419                 return false;
1420         }
1421         return static_cast<AlsaPort*>(port)->is_physically_connected ();
1422 }
1423
1424 int
1425 AlsaAudioBackend::get_connections (PortEngine::PortHandle port, std::vector<std::string>& names, bool /*process_callback_safe*/)
1426 {
1427         if (!valid_port (port)) {
1428                 PBD::error << _("AlsaBackend::get_connections: Invalid Port") << endmsg;
1429                 return -1;
1430         }
1431
1432         assert (0 == names.size ());
1433
1434         const std::vector<AlsaPort*>& connected_ports = static_cast<AlsaPort*>(port)->get_connections ();
1435
1436         for (std::vector<AlsaPort*>::const_iterator i = connected_ports.begin (); i != connected_ports.end (); ++i) {
1437                 names.push_back ((*i)->name ());
1438         }
1439
1440         return (int)names.size ();
1441 }
1442
1443 /* MIDI */
1444 int
1445 AlsaAudioBackend::midi_event_get (
1446                 pframes_t& timestamp,
1447                 size_t& size, uint8_t** buf, void* port_buffer,
1448                 uint32_t event_index)
1449 {
1450         assert (buf && port_buffer);
1451         AlsaMidiBuffer& source = * static_cast<AlsaMidiBuffer*>(port_buffer);
1452         if (event_index >= source.size ()) {
1453                 return -1;
1454         }
1455         AlsaMidiEvent * const event = source[event_index].get ();
1456
1457         timestamp = event->timestamp ();
1458         size = event->size ();
1459         *buf = event->data ();
1460         return 0;
1461 }
1462
1463 int
1464 AlsaAudioBackend::midi_event_put (
1465                 void* port_buffer,
1466                 pframes_t timestamp,
1467                 const uint8_t* buffer, size_t size)
1468 {
1469         assert (buffer && port_buffer);
1470         AlsaMidiBuffer& dst = * static_cast<AlsaMidiBuffer*>(port_buffer);
1471         if (dst.size () && (pframes_t)dst.back ()->timestamp () > timestamp) {
1472 #ifndef NDEBUG
1473                 // nevermind, ::get_buffer() sorts events
1474                 fprintf (stderr, "AlsaMidiBuffer: it's too late for this event. %d > %d\n",
1475                                 (pframes_t)dst.back ()->timestamp (), timestamp);
1476 #endif
1477         }
1478         dst.push_back (boost::shared_ptr<AlsaMidiEvent>(new AlsaMidiEvent (timestamp, buffer, size)));
1479         return 0;
1480 }
1481
1482 uint32_t
1483 AlsaAudioBackend::get_midi_event_count (void* port_buffer)
1484 {
1485         assert (port_buffer);
1486         return static_cast<AlsaMidiBuffer*>(port_buffer)->size ();
1487 }
1488
1489 void
1490 AlsaAudioBackend::midi_clear (void* port_buffer)
1491 {
1492         assert (port_buffer);
1493         AlsaMidiBuffer * buf = static_cast<AlsaMidiBuffer*>(port_buffer);
1494         assert (buf);
1495         buf->clear ();
1496 }
1497
1498 /* Monitoring */
1499
1500 bool
1501 AlsaAudioBackend::can_monitor_input () const
1502 {
1503         return false;
1504 }
1505
1506 int
1507 AlsaAudioBackend::request_input_monitoring (PortEngine::PortHandle, bool)
1508 {
1509         return -1;
1510 }
1511
1512 int
1513 AlsaAudioBackend::ensure_input_monitoring (PortEngine::PortHandle, bool)
1514 {
1515         return -1;
1516 }
1517
1518 bool
1519 AlsaAudioBackend::monitoring_input (PortEngine::PortHandle)
1520 {
1521         return false;
1522 }
1523
1524 /* Latency management */
1525
1526 void
1527 AlsaAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range)
1528 {
1529         if (!valid_port (port)) {
1530                 PBD::error << _("AlsaPort::set_latency_range (): invalid port.") << endmsg;
1531         }
1532         static_cast<AlsaPort*>(port)->set_latency_range (latency_range, for_playback);
1533 }
1534
1535 LatencyRange
1536 AlsaAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback)
1537 {
1538         LatencyRange r;
1539         if (!valid_port (port)) {
1540                 PBD::error << _("AlsaPort::get_latency_range (): invalid port.") << endmsg;
1541                 r.min = 0;
1542                 r.max = 0;
1543                 return r;
1544         }
1545         AlsaPort *p = static_cast<AlsaPort*>(port);
1546         assert(p);
1547
1548         r = p->latency_range (for_playback);
1549         if (p->is_physical() && p->is_terminal()) {
1550                 if (p->is_input() && for_playback) {
1551                         r.min += _samples_per_period;
1552                         r.max += _samples_per_period;
1553                 }
1554                 if (p->is_output() && !for_playback) {
1555                         r.min += _samples_per_period;
1556                         r.max += _samples_per_period;
1557                 }
1558         }
1559         return r;
1560 }
1561
1562 /* Discovering physical ports */
1563
1564 bool
1565 AlsaAudioBackend::port_is_physical (PortEngine::PortHandle port) const
1566 {
1567         if (!valid_port (port)) {
1568                 PBD::error << _("AlsaPort::port_is_physical (): invalid port.") << endmsg;
1569                 return false;
1570         }
1571         return static_cast<AlsaPort*>(port)->is_physical ();
1572 }
1573
1574 void
1575 AlsaAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>& port_names)
1576 {
1577         for (size_t i = 0; i < _ports.size (); ++i) {
1578                 AlsaPort* port = _ports[i];
1579                 if ((port->type () == type) && port->is_input () && port->is_physical ()) {
1580                         port_names.push_back (port->name ());
1581                 }
1582         }
1583 }
1584
1585 void
1586 AlsaAudioBackend::get_physical_inputs (DataType type, std::vector<std::string>& port_names)
1587 {
1588         for (size_t i = 0; i < _ports.size (); ++i) {
1589                 AlsaPort* port = _ports[i];
1590                 if ((port->type () == type) && port->is_output () && port->is_physical ()) {
1591                         port_names.push_back (port->name ());
1592                 }
1593         }
1594 }
1595
1596 ChanCount
1597 AlsaAudioBackend::n_physical_outputs () const
1598 {
1599         int n_midi = 0;
1600         int n_audio = 0;
1601         for (size_t i = 0; i < _ports.size (); ++i) {
1602                 AlsaPort* port = _ports[i];
1603                 if (port->is_output () && port->is_physical ()) {
1604                         switch (port->type ()) {
1605                                 case DataType::AUDIO: ++n_audio; break;
1606                                 case DataType::MIDI: ++n_midi; break;
1607                                 default: break;
1608                         }
1609                 }
1610         }
1611         ChanCount cc;
1612         cc.set (DataType::AUDIO, n_audio);
1613         cc.set (DataType::MIDI, n_midi);
1614         return cc;
1615 }
1616
1617 ChanCount
1618 AlsaAudioBackend::n_physical_inputs () const
1619 {
1620         int n_midi = 0;
1621         int n_audio = 0;
1622         for (size_t i = 0; i < _ports.size (); ++i) {
1623                 AlsaPort* port = _ports[i];
1624                 if (port->is_input () && port->is_physical ()) {
1625                         switch (port->type ()) {
1626                                 case DataType::AUDIO: ++n_audio; break;
1627                                 case DataType::MIDI: ++n_midi; break;
1628                                 default: break;
1629                         }
1630                 }
1631         }
1632         ChanCount cc;
1633         cc.set (DataType::AUDIO, n_audio);
1634         cc.set (DataType::MIDI, n_midi);
1635         return cc;
1636 }
1637
1638 /* Getting access to the data buffer for a port */
1639
1640 void*
1641 AlsaAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes)
1642 {
1643         assert (port);
1644         assert (valid_port (port));
1645         return static_cast<AlsaPort*>(port)->get_buffer (nframes);
1646 }
1647
1648 /* Engine Process */
1649 void *
1650 AlsaAudioBackend::main_process_thread ()
1651 {
1652         AudioEngine::thread_init_callback (this);
1653         _active = true;
1654         _processed_samples = 0;
1655
1656         uint64_t clock1;
1657         _pcmi->pcm_start ();
1658         int no_proc_errors = 0;
1659         const int bailout = 2 * _samplerate / _samples_per_period;
1660
1661         manager.registration_callback();
1662         manager.graph_order_callback();
1663
1664         while (_run) {
1665                 long nr;
1666                 bool xrun = false;
1667
1668                 if (_freewheeling != _freewheel) {
1669                         _freewheel = _freewheeling;
1670                         engine.freewheel_callback (_freewheel);
1671                 }
1672
1673                 if (!_freewheel) {
1674                         nr = _pcmi->pcm_wait ();
1675
1676                         if (_pcmi->state () > 0) {
1677                                 ++no_proc_errors;
1678                                 xrun = true;
1679                         }
1680                         if (_pcmi->state () < 0) {
1681                                 PBD::error << _("AlsaAudioBackend: I/O error. Audio Process Terminated.") << endmsg;
1682                                 break;
1683                         }
1684                         if (no_proc_errors > bailout) {
1685                                 PBD::error
1686                                         << string_compose (
1687                                                         _("AlsaAudioBackend: Audio Process Terminated after %1 consecutive x-runs."),
1688                                                         no_proc_errors)
1689                                         << endmsg;
1690                                 break;
1691                         }
1692
1693                         while (nr >= (long)_samples_per_period && _freewheeling == _freewheel) {
1694                                 uint32_t i = 0;
1695                                 clock1 = g_get_monotonic_time();
1696                                 no_proc_errors = 0;
1697
1698                                 _pcmi->capt_init (_samples_per_period);
1699                                 for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++i) {
1700                                         _pcmi->capt_chan (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period);
1701                                 }
1702                                 _pcmi->capt_done (_samples_per_period);
1703
1704                                 /* de-queue incoming midi*/
1705                                 i = 0;
1706                                 for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
1707                                         assert (_rmidi_in.size() > i);
1708                                         AlsaMidiIn *rm = _rmidi_in.at(i);
1709                                         void *bptr = (*it)->get_buffer(0);
1710                                         pframes_t time;
1711                                         uint8_t data[64]; // match MaxAlsaEventSize in alsa_rawmidi.cc
1712                                         size_t size = sizeof(data);
1713                                         midi_clear(bptr);
1714                                         while (rm->recv_event (time, data, size)) {
1715                                                 midi_event_put(bptr, time, data, size);
1716                                                 size = sizeof(data);
1717                                         }
1718                                         rm->sync_time (clock1);
1719                                 }
1720
1721                                 for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
1722                                         memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
1723                                 }
1724
1725                                 /* call engine process callback */
1726                                 _last_process_start = g_get_monotonic_time();
1727                                 if (engine.process_callback (_samples_per_period)) {
1728                                         _pcmi->pcm_stop ();
1729                                         _active = false;
1730                                         return 0;
1731                                 }
1732
1733                                 for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
1734                                         static_cast<AlsaMidiPort*>(*it)->next_period();
1735                                 }
1736
1737                                 /* queue outgoing midi */
1738                                 i = 0;
1739                                 for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
1740                                         assert (_rmidi_out.size() > i);
1741                                         const AlsaMidiBuffer * src = static_cast<const AlsaMidiPort*>(*it)->const_buffer();
1742                                         AlsaMidiOut *rm = _rmidi_out.at(i);
1743                                         rm->sync_time (clock1);
1744                                         for (AlsaMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) {
1745                                                 rm->send_event ((*mit)->timestamp(), (*mit)->data(), (*mit)->size());
1746                                         }
1747                                 }
1748
1749                                 /* write back audio */
1750                                 i = 0;
1751                                 _pcmi->play_init (_samples_per_period);
1752                                 for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it, ++i) {
1753                                         _pcmi->play_chan (i, (const float*)(*it)->get_buffer (_samples_per_period), _samples_per_period);
1754                                 }
1755                                 for (; i < _pcmi->nplay (); ++i) {
1756                                         _pcmi->clear_chan (i, _samples_per_period);
1757                                 }
1758                                 _pcmi->play_done (_samples_per_period);
1759                                 nr -= _samples_per_period;
1760                                 _processed_samples += _samples_per_period;
1761
1762                                 _dsp_load_calc.set_max_time(_samplerate, _samples_per_period);
1763                                 _dsp_load_calc.set_start_timestamp_us (clock1);
1764                                 _dsp_load_calc.set_stop_timestamp_us (g_get_monotonic_time());
1765                                 _dsp_load = _dsp_load_calc.get_dsp_load ();
1766                         }
1767
1768                         if (xrun && (_pcmi->capt_xrun() > 0 || _pcmi->play_xrun() > 0)) {
1769                                 engine.Xrun ();
1770 #if 0
1771                                 fprintf(stderr, "ALSA x-run read: %.2f ms, write: %.2f ms\n",
1772                                                 _pcmi->capt_xrun() * 1000.0, _pcmi->play_xrun() * 1000.0);
1773 #endif
1774                         }
1775                 } else {
1776                         // Freewheelin'
1777
1778                         // zero audio input buffers
1779                         for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
1780                                 memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
1781                         }
1782
1783                         clock1 = g_get_monotonic_time();
1784                         uint32_t i = 0;
1785                         for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
1786                                 static_cast<AlsaMidiBuffer*>((*it)->get_buffer(0))->clear ();
1787                                 AlsaMidiIn *rm = _rmidi_in.at(i);
1788                                 void *bptr = (*it)->get_buffer(0);
1789                                 midi_clear(bptr); // zero midi buffer
1790
1791                                 // TODO add an API call for this.
1792                                 pframes_t time;
1793                                 uint8_t data[64]; // match MaxAlsaEventSize in alsa_rawmidi.cc
1794                                 size_t size = sizeof(data);
1795                                 while (rm->recv_event (time, data, size)) {
1796                                         ; // discard midi-data from HW.
1797                                 }
1798                                 rm->sync_time (clock1);
1799                         }
1800
1801                         _last_process_start = 0;
1802                         if (engine.process_callback (_samples_per_period)) {
1803                                 _pcmi->pcm_stop ();
1804                                 _active = false;
1805                                 return 0;
1806                         }
1807
1808                         // drop all outgoing MIDI messages
1809                         for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
1810                                         void *bptr = (*it)->get_buffer(0);
1811                                         midi_clear(bptr);
1812                         }
1813
1814                         _dsp_load = 1.0;
1815                         Glib::usleep (100); // don't hog cpu
1816                 }
1817
1818                 bool connections_changed = false;
1819                 bool ports_changed = false;
1820                 if (!pthread_mutex_trylock (&_port_callback_mutex)) {
1821                         if (_port_change_flag) {
1822                                 ports_changed = true;
1823                                 _port_change_flag = false;
1824                         }
1825                         if (!_port_connection_queue.empty ()) {
1826                                 connections_changed = true;
1827                         }
1828                         while (!_port_connection_queue.empty ()) {
1829                                 PortConnectData *c = _port_connection_queue.back ();
1830                                 manager.connect_callback (c->a, c->b, c->c);
1831                                 _port_connection_queue.pop_back ();
1832                                 delete c;
1833                         }
1834                         pthread_mutex_unlock (&_port_callback_mutex);
1835                 }
1836                 if (ports_changed) {
1837                         manager.registration_callback();
1838                 }
1839                 if (connections_changed) {
1840                         manager.graph_order_callback();
1841                 }
1842                 if (connections_changed || ports_changed) {
1843                         engine.latency_callback(false);
1844                         engine.latency_callback(true);
1845                 }
1846
1847         }
1848         _pcmi->pcm_stop ();
1849         _active = false;
1850         if (_run) {
1851                 engine.halted_callback("ALSA I/O error.");
1852         }
1853         return 0;
1854 }
1855
1856
1857 /******************************************************************************/
1858
1859 static boost::shared_ptr<AlsaAudioBackend> _instance;
1860
1861 static boost::shared_ptr<AudioBackend> backend_factory (AudioEngine& e);
1862 static int instantiate (const std::string& arg1, const std::string& /* arg2 */);
1863 static int deinstantiate ();
1864 static bool already_configured ();
1865 static bool available ();
1866
1867 static ARDOUR::AudioBackendInfo _descriptor = {
1868         "ALSA",
1869         instantiate,
1870         deinstantiate,
1871         backend_factory,
1872         already_configured,
1873         available
1874 };
1875
1876 static boost::shared_ptr<AudioBackend>
1877 backend_factory (AudioEngine& e)
1878 {
1879         if (!_instance) {
1880                 _instance.reset (new AlsaAudioBackend (e, _descriptor));
1881         }
1882         return _instance;
1883 }
1884
1885 static int
1886 instantiate (const std::string& arg1, const std::string& /* arg2 */)
1887 {
1888         s_instance_name = arg1;
1889         return 0;
1890 }
1891
1892 static int
1893 deinstantiate ()
1894 {
1895         _instance.reset ();
1896         return 0;
1897 }
1898
1899 static bool
1900 already_configured ()
1901 {
1902         return false;
1903 }
1904
1905 static bool
1906 available ()
1907 {
1908         return true;
1909 }
1910
1911 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
1912 {
1913         return &_descriptor;
1914 }
1915
1916
1917 /******************************************************************************/
1918 AlsaPort::AlsaPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
1919         : _alsa_backend (b)
1920         , _name  (name)
1921         , _flags (flags)
1922 {
1923         _capture_latency_range.min = 0;
1924         _capture_latency_range.max = 0;
1925         _playback_latency_range.min = 0;
1926         _playback_latency_range.max = 0;
1927 }
1928
1929 AlsaPort::~AlsaPort () {
1930         disconnect_all ();
1931 }
1932
1933
1934 int AlsaPort::connect (AlsaPort *port)
1935 {
1936         if (!port) {
1937                 PBD::error << _("AlsaPort::connect (): invalid (null) port") << endmsg;
1938                 return -1;
1939         }
1940
1941         if (type () != port->type ()) {
1942                 PBD::error << _("AlsaPort::connect (): wrong port-type") << endmsg;
1943                 return -1;
1944         }
1945
1946         if (is_output () && port->is_output ()) {
1947                 PBD::error << _("AlsaPort::connect (): cannot inter-connect output ports.") << endmsg;
1948                 return -1;
1949         }
1950
1951         if (is_input () && port->is_input ()) {
1952                 PBD::error << _("AlsaPort::connect (): cannot inter-connect input ports.") << endmsg;
1953                 return -1;
1954         }
1955
1956         if (this == port) {
1957                 PBD::error << _("AlsaPort::connect (): cannot self-connect ports.") << endmsg;
1958                 return -1;
1959         }
1960
1961         if (is_connected (port)) {
1962 #if 0 // don't bother to warn about this for now. just ignore it
1963                 PBD::error << _("AlsaPort::connect (): ports are already connected:")
1964                         << " (" << name () << ") -> (" << port->name () << ")"
1965                         << endmsg;
1966 #endif
1967                 return -1;
1968         }
1969
1970         _connect (port, true);
1971         return 0;
1972 }
1973
1974
1975 void AlsaPort::_connect (AlsaPort *port, bool callback)
1976 {
1977         _connections.push_back (port);
1978         if (callback) {
1979                 port->_connect (this, false);
1980                 _alsa_backend.port_connect_callback (name(),  port->name(), true);
1981         }
1982 }
1983
1984 int AlsaPort::disconnect (AlsaPort *port)
1985 {
1986         if (!port) {
1987                 PBD::error << _("AlsaPort::disconnect (): invalid (null) port") << endmsg;
1988                 return -1;
1989         }
1990
1991         if (!is_connected (port)) {
1992                 PBD::error << _("AlsaPort::disconnect (): ports are not connected:")
1993                         << " (" << name () << ") -> (" << port->name () << ")"
1994                         << endmsg;
1995                 return -1;
1996         }
1997         _disconnect (port, true);
1998         return 0;
1999 }
2000
2001 void AlsaPort::_disconnect (AlsaPort *port, bool callback)
2002 {
2003         std::vector<AlsaPort*>::iterator it = std::find (_connections.begin (), _connections.end (), port);
2004
2005         assert (it != _connections.end ());
2006
2007         _connections.erase (it);
2008
2009         if (callback) {
2010                 port->_disconnect (this, false);
2011                 _alsa_backend.port_connect_callback (name(),  port->name(), false);
2012         }
2013 }
2014
2015
2016 void AlsaPort::disconnect_all ()
2017 {
2018         while (!_connections.empty ()) {
2019                 _connections.back ()->_disconnect (this, false);
2020                 _alsa_backend.port_connect_callback (name(),  _connections.back ()->name(), false);
2021                 _connections.pop_back ();
2022         }
2023 }
2024
2025 bool
2026 AlsaPort::is_connected (const AlsaPort *port) const
2027 {
2028         return std::find (_connections.begin (), _connections.end (), port) != _connections.end ();
2029 }
2030
2031 bool AlsaPort::is_physically_connected () const
2032 {
2033         for (std::vector<AlsaPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
2034                 if ((*it)->is_physical ()) {
2035                         return true;
2036                 }
2037         }
2038         return false;
2039 }
2040
2041 /******************************************************************************/
2042
2043 AlsaAudioPort::AlsaAudioPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
2044         : AlsaPort (b, name, flags)
2045 {
2046         memset (_buffer, 0, sizeof (_buffer));
2047         mlock(_buffer, sizeof (_buffer));
2048 }
2049
2050 AlsaAudioPort::~AlsaAudioPort () { }
2051
2052 void* AlsaAudioPort::get_buffer (pframes_t n_samples)
2053 {
2054         if (is_input ()) {
2055                 std::vector<AlsaPort*>::const_iterator it = get_connections ().begin ();
2056                 if (it == get_connections ().end ()) {
2057                         memset (_buffer, 0, n_samples * sizeof (Sample));
2058                 } else {
2059                         AlsaAudioPort const * source = static_cast<const AlsaAudioPort*>(*it);
2060                         assert (source && source->is_output ());
2061                         memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
2062                         while (++it != get_connections ().end ()) {
2063                                 source = static_cast<const AlsaAudioPort*>(*it);
2064                                 assert (source && source->is_output ());
2065                                 Sample* dst = buffer ();
2066                                 const Sample* src = source->const_buffer ();
2067                                 for (uint32_t s = 0; s < n_samples; ++s, ++dst, ++src) {
2068                                         *dst += *src;
2069                                 }
2070                         }
2071                 }
2072         }
2073         return _buffer;
2074 }
2075
2076
2077 AlsaMidiPort::AlsaMidiPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
2078         : AlsaPort (b, name, flags)
2079         , _n_periods (1)
2080         , _bufperiod (0)
2081 {
2082         _buffer[0].clear ();
2083         _buffer[1].clear ();
2084 }
2085
2086 AlsaMidiPort::~AlsaMidiPort () { }
2087
2088 struct MidiEventSorter {
2089         bool operator() (const boost::shared_ptr<AlsaMidiEvent>& a, const boost::shared_ptr<AlsaMidiEvent>& b) {
2090                 return *a < *b;
2091         }
2092 };
2093
2094 void* AlsaMidiPort::get_buffer (pframes_t /* nframes */)
2095 {
2096         if (is_input ()) {
2097                 (_buffer[_bufperiod]).clear ();
2098                 for (std::vector<AlsaPort*>::const_iterator i = get_connections ().begin ();
2099                                 i != get_connections ().end ();
2100                                 ++i) {
2101                         const AlsaMidiBuffer * src = static_cast<const AlsaMidiPort*>(*i)->const_buffer ();
2102                         for (AlsaMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
2103                                 (_buffer[_bufperiod]).push_back (boost::shared_ptr<AlsaMidiEvent>(new AlsaMidiEvent (**it)));
2104                         }
2105                 }
2106                 std::sort ((_buffer[_bufperiod]).begin (), (_buffer[_bufperiod]).end (), MidiEventSorter());
2107         }
2108         return &(_buffer[_bufperiod]);
2109 }
2110
2111 AlsaMidiEvent::AlsaMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size)
2112         : _size (size)
2113         , _timestamp (timestamp)
2114         , _data (0)
2115 {
2116         if (size > 0) {
2117                 _data = (uint8_t*) malloc (size);
2118                 memcpy (_data, data, size);
2119         }
2120 }
2121
2122 AlsaMidiEvent::AlsaMidiEvent (const AlsaMidiEvent& other)
2123         : _size (other.size ())
2124         , _timestamp (other.timestamp ())
2125         , _data (0)
2126 {
2127         if (other.size () && other.const_data ()) {
2128                 _data = (uint8_t*) malloc (other.size ());
2129                 memcpy (_data, other.const_data (), other.size ());
2130         }
2131 };
2132
2133 AlsaMidiEvent::~AlsaMidiEvent () {
2134         free (_data);
2135 };