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