Increase alsa-backend timeout
[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 <boost/foreach.hpp>
27 #include <boost/tokenizer.hpp>
28
29 #include "alsa_audiobackend.h"
30
31 #include "pbd/compose.h"
32 #include "pbd/convert.h"
33 #include "pbd/error.h"
34 #include "pbd/file_utils.h"
35 #include "pbd/pthread_utils.h"
36
37 #include "ardour/filesystem_paths.h"
38 #include "ardour/port_manager.h"
39 #include "ardouralsautil/devicelist.h"
40 #include "pbd/i18n.h"
41
42 using namespace ARDOUR;
43
44 static std::string s_instance_name;
45 size_t AlsaAudioBackend::_max_buffer_size = 8192;
46 std::vector<std::string> AlsaAudioBackend::_midi_options;
47 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_input_audio_device_status;
48 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_output_audio_device_status;
49 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_duplex_audio_device_status;
50 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_midi_device_status;
51
52 ALSADeviceInfo AlsaAudioBackend::_input_audio_device_info;
53 ALSADeviceInfo AlsaAudioBackend::_output_audio_device_info;
54
55 AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
56         : AudioBackend (e, info)
57         , _pcmi (0)
58         , _run (false)
59         , _active (false)
60         , _freewheel (false)
61         , _freewheeling (false)
62         , _measure_latency (false)
63         , _last_process_start (0)
64         , _input_audio_device("")
65         , _output_audio_device("")
66         , _midi_driver_option(get_standard_device_name(DeviceNone))
67         , _samplerate (48000)
68         , _samples_per_period (1024)
69         , _periods_per_cycle (2)
70         , _n_inputs (0)
71         , _n_outputs (0)
72         , _systemic_audio_input_latency (0)
73         , _systemic_audio_output_latency (0)
74         , _dsp_load (0)
75         , _processed_samples (0)
76         , _midi_ins (0)
77         , _midi_outs (0)
78         , _port_change_flag (false)
79 {
80         _instance_name = s_instance_name;
81         pthread_mutex_init (&_port_callback_mutex, 0);
82         _input_audio_device_info.valid = false;
83         _output_audio_device_info.valid = false;
84
85         _port_connection_queue.reserve (128);
86 }
87
88 AlsaAudioBackend::~AlsaAudioBackend ()
89 {
90         pthread_mutex_destroy (&_port_callback_mutex);
91 }
92
93 /* AUDIOBACKEND API */
94
95 std::string
96 AlsaAudioBackend::name () const
97 {
98         return X_("ALSA");
99 }
100
101 bool
102 AlsaAudioBackend::is_realtime () const
103 {
104         return true;
105 }
106
107 std::vector<AudioBackend::DeviceStatus>
108 AlsaAudioBackend::enumerate_devices () const
109 {
110         _duplex_audio_device_status.clear();
111         std::map<std::string, std::string> devices;
112         get_alsa_audio_device_names(devices);
113         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
114                 if (_input_audio_device == "") _input_audio_device = i->first;
115                 if (_output_audio_device == "") _output_audio_device = i->first;
116                 _duplex_audio_device_status.push_back (DeviceStatus (i->first, true));
117         }
118         return _duplex_audio_device_status;
119 }
120
121 std::vector<AudioBackend::DeviceStatus>
122 AlsaAudioBackend::enumerate_input_devices () const
123 {
124         _input_audio_device_status.clear();
125         std::map<std::string, std::string> devices;
126         get_alsa_audio_device_names(devices, HalfDuplexIn);
127         _input_audio_device_status.push_back (DeviceStatus (get_standard_device_name(DeviceNone), true));
128         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
129                 if (_input_audio_device == "") _input_audio_device = i->first;
130                 _input_audio_device_status.push_back (DeviceStatus (i->first, true));
131         }
132         return _input_audio_device_status;
133 }
134
135 std::vector<AudioBackend::DeviceStatus>
136 AlsaAudioBackend::enumerate_output_devices () const
137 {
138         _output_audio_device_status.clear();
139         std::map<std::string, std::string> devices;
140         get_alsa_audio_device_names(devices, HalfDuplexOut);
141         _output_audio_device_status.push_back (DeviceStatus (get_standard_device_name(DeviceNone), true));
142         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
143                 if (_output_audio_device == "") _output_audio_device = i->first;
144                 _output_audio_device_status.push_back (DeviceStatus (i->first, true));
145         }
146         return _output_audio_device_status;
147 }
148
149 std::vector<float>
150 AlsaAudioBackend::available_sample_rates2 (const std::string& input_device, const std::string& output_device) const
151 {
152         std::vector<float> sr;
153         if (input_device == get_standard_device_name(DeviceNone) && output_device == get_standard_device_name(DeviceNone)) {
154                 return sr;
155         }
156         else if (input_device == get_standard_device_name(DeviceNone)) {
157                 sr = available_sample_rates (output_device);
158         }
159         else if (output_device == get_standard_device_name(DeviceNone)) {
160                 sr = available_sample_rates (input_device);
161         } else {
162                 std::vector<float> sr_in =  available_sample_rates (input_device);
163                 std::vector<float> sr_out = available_sample_rates (output_device);
164                 std::set_intersection (sr_in.begin(), sr_in.end(), sr_out.begin(), sr_out.end(), std::back_inserter(sr));
165         }
166         return sr;
167 }
168
169 std::vector<float>
170 AlsaAudioBackend::available_sample_rates (const std::string& device) const
171 {
172         ALSADeviceInfo *nfo = NULL;
173         std::vector<float> sr;
174         if (device == get_standard_device_name(DeviceNone)) {
175                 return sr;
176         }
177         if (device == _input_audio_device && _input_audio_device_info.valid) {
178                 nfo = &_input_audio_device_info;
179         }
180         else if (device == _output_audio_device && _output_audio_device_info.valid) {
181                 nfo = &_output_audio_device_info;
182         }
183
184         static const float avail_rates [] = { 8000, 22050.0, 24000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 };
185
186         for (size_t i = 0 ; i < sizeof(avail_rates) / sizeof(float); ++i) {
187                 if (!nfo || (avail_rates[i] >= nfo->min_rate && avail_rates[i] <= nfo->max_rate)) {
188                         sr.push_back (avail_rates[i]);
189                 }
190         }
191
192         return sr;
193 }
194
195 std::vector<uint32_t>
196 AlsaAudioBackend::available_buffer_sizes2 (const std::string& input_device, const std::string& output_device) const
197 {
198         std::vector<uint32_t> bs;
199         if (input_device == get_standard_device_name(DeviceNone) && output_device == get_standard_device_name(DeviceNone)) {
200                 return bs;
201         }
202         else if (input_device == get_standard_device_name(DeviceNone)) {
203                 bs = available_buffer_sizes (output_device);
204         }
205         else if (output_device == get_standard_device_name(DeviceNone)) {
206                 bs = available_buffer_sizes (input_device);
207         } else {
208                 std::vector<uint32_t> bs_in =  available_buffer_sizes (input_device);
209                 std::vector<uint32_t> bs_out = available_buffer_sizes (output_device);
210                 std::set_intersection (bs_in.begin(), bs_in.end(), bs_out.begin(), bs_out.end(), std::back_inserter(bs));
211         }
212         return bs;
213 }
214
215 std::vector<uint32_t>
216 AlsaAudioBackend::available_buffer_sizes (const std::string& device) const
217 {
218         ALSADeviceInfo *nfo = NULL;
219         std::vector<uint32_t> bs;
220         if (device == get_standard_device_name(DeviceNone)) {
221                 return bs;
222         }
223         if (device == _input_audio_device && _input_audio_device_info.valid) {
224                 nfo = &_input_audio_device_info;
225         }
226         else if (device == _output_audio_device && _output_audio_device_info.valid) {
227                 nfo = &_output_audio_device_info;
228         }
229
230         static const unsigned long avail_sizes [] = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
231
232         for (size_t i = 0 ; i < sizeof(avail_sizes) / sizeof(unsigned long); ++i) {
233                 if (!nfo || (avail_sizes[i] >= nfo->min_size && avail_sizes[i] <= nfo->max_size)) {
234                         bs.push_back (avail_sizes[i]);
235                 }
236         }
237         return bs;
238 }
239
240 uint32_t
241 AlsaAudioBackend::available_input_channel_count (const std::string& device) const
242 {
243         if (device == get_standard_device_name(DeviceNone)) {
244                 return 0;
245         }
246         if (device == _input_audio_device && _input_audio_device_info.valid) {
247                 return _input_audio_device_info.max_channels;
248         }
249         return 128;
250 }
251
252 uint32_t
253 AlsaAudioBackend::available_output_channel_count (const std::string& device) const
254 {
255         if (device == get_standard_device_name(DeviceNone)) {
256                 return 0;
257         }
258         if (device == _output_audio_device && _output_audio_device_info.valid) {
259                 return _output_audio_device_info.max_channels;
260         }
261         return 128;
262 }
263
264 std::vector<uint32_t>
265 AlsaAudioBackend::available_period_sizes (const std::string& driver) const
266 {
267         std::vector<uint32_t> ps;
268         ps.push_back (2);
269         ps.push_back (3);
270         return ps;
271 }
272
273 bool
274 AlsaAudioBackend::can_change_sample_rate_when_running () const
275 {
276         return false;
277 }
278
279 bool
280 AlsaAudioBackend::can_change_buffer_size_when_running () const
281 {
282         return false; // why not? :)
283 }
284
285 int
286 AlsaAudioBackend::set_input_device_name (const std::string& d)
287 {
288         if (_input_audio_device == d) {
289                 return 0;
290         }
291         _input_audio_device = d;
292
293         if (d == get_standard_device_name(DeviceNone)) {
294                 _input_audio_device_info.valid = false;
295                 return 0;
296         }
297         std::string alsa_device;
298         std::map<std::string, std::string> devices;
299
300         get_alsa_audio_device_names(devices, HalfDuplexIn);
301         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
302                 if (i->first == d) {
303                         alsa_device = i->second;
304                         break;
305                 }
306         }
307         if (alsa_device == "") {
308                 _input_audio_device_info.valid = false;
309                 return 1;
310         }
311         /* device will be busy once used, hence cache the parameters */
312         /* return */ get_alsa_device_parameters (alsa_device.c_str(), true, &_input_audio_device_info);
313         return 0;
314 }
315
316 int
317 AlsaAudioBackend::set_output_device_name (const std::string& d)
318 {
319         if (_output_audio_device == d) {
320                 return 0;
321         }
322
323         _output_audio_device = d;
324
325         if (d == get_standard_device_name(DeviceNone)) {
326                 _output_audio_device_info.valid = false;
327                 return 0;
328         }
329         std::string alsa_device;
330         std::map<std::string, std::string> devices;
331
332         get_alsa_audio_device_names(devices, HalfDuplexOut);
333         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
334                 if (i->first == d) {
335                         alsa_device = i->second;
336                         break;
337                 }
338         }
339         if (alsa_device == "") {
340                 _output_audio_device_info.valid = false;
341                 return 1;
342         }
343         /* return */ get_alsa_device_parameters (alsa_device.c_str(), true, &_output_audio_device_info);
344         return 0;
345 }
346
347 int
348 AlsaAudioBackend::set_device_name (const std::string& d)
349 {
350         int rv = 0;
351         rv |= set_input_device_name (d);
352         rv |= set_output_device_name (d);
353         return rv;
354 }
355
356 int
357 AlsaAudioBackend::set_sample_rate (float sr)
358 {
359         if (sr <= 0) { return -1; }
360         _samplerate = sr;
361         engine.sample_rate_change (sr);
362         return 0;
363 }
364
365 int
366 AlsaAudioBackend::set_peridod_size (uint32_t n)
367 {
368         if (n == 0 || n > 3) {
369                 return -1;
370         }
371         if (_run) {
372                 return -1;
373         }
374         _periods_per_cycle = n;
375         return 0;
376 }
377
378 int
379 AlsaAudioBackend::set_buffer_size (uint32_t bs)
380 {
381         if (bs <= 0 || bs >= _max_buffer_size) {
382                 return -1;
383         }
384         if (_run) {
385                 return -1;
386         }
387         _samples_per_period = bs;
388         engine.buffer_size_change (bs);
389         return 0;
390 }
391
392 int
393 AlsaAudioBackend::set_interleaved (bool yn)
394 {
395         if (!yn) { return 0; }
396         return -1;
397 }
398
399 int
400 AlsaAudioBackend::set_input_channels (uint32_t cc)
401 {
402         _n_inputs = cc;
403         return 0;
404 }
405
406 int
407 AlsaAudioBackend::set_output_channels (uint32_t cc)
408 {
409         _n_outputs = cc;
410         return 0;
411 }
412
413 int
414 AlsaAudioBackend::set_systemic_input_latency (uint32_t sl)
415 {
416         _systemic_audio_input_latency = sl;
417         if (_run) {
418                 update_systemic_audio_latencies();
419         }
420         return 0;
421 }
422
423 int
424 AlsaAudioBackend::set_systemic_output_latency (uint32_t sl)
425 {
426         _systemic_audio_output_latency = sl;
427         if (_run) {
428                 update_systemic_audio_latencies();
429         }
430         return 0;
431 }
432
433 int
434 AlsaAudioBackend::set_systemic_midi_input_latency (std::string const device, uint32_t sl)
435 {
436         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
437         if (!nfo) return -1;
438         nfo->systemic_input_latency = sl;
439         if (_run && nfo->enabled) {
440                 update_systemic_midi_latencies ();
441         }
442         return 0;
443 }
444
445 int
446 AlsaAudioBackend::set_systemic_midi_output_latency (std::string const device, uint32_t sl)
447 {
448         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
449         if (!nfo) return -1;
450         nfo->systemic_output_latency = sl;
451         if (_run && nfo->enabled) {
452                 update_systemic_midi_latencies ();
453         }
454         return 0;
455 }
456
457 void
458 AlsaAudioBackend::update_systemic_audio_latencies ()
459 {
460         const uint32_t lcpp = (_periods_per_cycle - 2) * _samples_per_period;
461         LatencyRange lr;
462
463         lr.min = lr.max = lcpp + (_measure_latency ? 0 : _systemic_audio_input_latency);
464         for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
465                 set_latency_range (*it, true, lr);
466         }
467
468         lr.min = lr.max = (_measure_latency ? 0 : _systemic_audio_output_latency);
469         for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
470                 set_latency_range (*it, false, lr);
471         }
472         update_latencies ();
473 }
474
475 void
476 AlsaAudioBackend::update_systemic_midi_latencies ()
477 {
478         uint32_t i = 0;
479         for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
480                 assert (_rmidi_out.size() > i);
481                 AlsaMidiOut *rm = _rmidi_out.at(i);
482                 struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
483                 assert (nfo);
484                 LatencyRange lr;
485                 lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_output_latency);
486                 set_latency_range (*it, false, lr);
487         }
488
489         i = 0;
490         for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
491                 assert (_rmidi_in.size() > i);
492                 AlsaMidiIO *rm = _rmidi_in.at(i);
493                 struct AlsaMidiDeviceInfo * nfo = midi_device_info (rm->name());
494                 assert (nfo);
495                 LatencyRange lr;
496                 lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_input_latency);
497                 set_latency_range (*it, true, lr);
498         }
499         update_latencies ();
500 }
501
502 /* Retrieving parameters */
503 std::string
504 AlsaAudioBackend::device_name () const
505 {
506         if (_input_audio_device != get_standard_device_name(DeviceNone)) {
507                 return _input_audio_device;
508         }
509         if (_output_audio_device != get_standard_device_name(DeviceNone)) {
510                 return _output_audio_device;
511         }
512         return "";
513 }
514
515 std::string
516 AlsaAudioBackend::input_device_name () const
517 {
518         return _input_audio_device;
519 }
520
521 std::string
522 AlsaAudioBackend::output_device_name () const
523 {
524         return _output_audio_device;
525 }
526
527 float
528 AlsaAudioBackend::sample_rate () const
529 {
530         return _samplerate;
531 }
532
533 uint32_t
534 AlsaAudioBackend::buffer_size () const
535 {
536         return _samples_per_period;
537 }
538
539 uint32_t
540 AlsaAudioBackend::period_size () const
541 {
542         return _periods_per_cycle;
543 }
544
545 bool
546 AlsaAudioBackend::interleaved () const
547 {
548         return false;
549 }
550
551 uint32_t
552 AlsaAudioBackend::input_channels () const
553 {
554         return _n_inputs;
555 }
556
557 uint32_t
558 AlsaAudioBackend::output_channels () const
559 {
560         return _n_outputs;
561 }
562
563 uint32_t
564 AlsaAudioBackend::systemic_input_latency () const
565 {
566         return _systemic_audio_input_latency;
567 }
568
569 uint32_t
570 AlsaAudioBackend::systemic_output_latency () const
571 {
572         return _systemic_audio_output_latency;
573 }
574
575 uint32_t
576 AlsaAudioBackend::systemic_midi_input_latency (std::string const device) const
577 {
578         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
579         if (!nfo) return 0;
580         return nfo->systemic_input_latency;
581 }
582
583 uint32_t
584 AlsaAudioBackend::systemic_midi_output_latency (std::string const device) const
585 {
586         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
587         if (!nfo) return 0;
588         return nfo->systemic_output_latency;
589 }
590
591 /* MIDI */
592 struct AlsaAudioBackend::AlsaMidiDeviceInfo *
593 AlsaAudioBackend::midi_device_info(std::string const name) const {
594         for (std::map<std::string, struct AlsaMidiDeviceInfo*>::const_iterator i = _midi_devices.begin (); i != _midi_devices.end(); ++i) {
595                 if (i->first == name) {
596                         return (i->second);
597                 }
598         }
599
600         assert(_midi_driver_option != get_standard_device_name(DeviceNone));
601
602         std::map<std::string, std::string> devices;
603         if (_midi_driver_option == _("ALSA raw devices")) {
604                 get_alsa_rawmidi_device_names(devices);
605         } else {
606                 get_alsa_sequencer_names (devices);
607         }
608
609         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
610                 if (i->first == name) {
611                         _midi_devices[name] = new AlsaMidiDeviceInfo();
612                         return _midi_devices[name];
613                 }
614         }
615         return 0;
616 }
617
618 std::vector<std::string>
619 AlsaAudioBackend::enumerate_midi_options () const
620 {
621         if (_midi_options.empty()) {
622                 _midi_options.push_back (_("ALSA raw devices"));
623                 _midi_options.push_back (_("ALSA sequencer"));
624                 _midi_options.push_back (get_standard_device_name(DeviceNone));
625         }
626         return _midi_options;
627 }
628
629 std::vector<AudioBackend::DeviceStatus>
630 AlsaAudioBackend::enumerate_midi_devices () const
631 {
632         _midi_device_status.clear();
633         std::map<std::string, std::string> devices;
634
635         if (_midi_driver_option == _("ALSA raw devices")) {
636                 get_alsa_rawmidi_device_names (devices);
637         }
638         else if (_midi_driver_option == _("ALSA sequencer")) {
639                 get_alsa_sequencer_names (devices);
640         }
641
642         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
643                 _midi_device_status.push_back (DeviceStatus (i->first, true));
644         }
645         return _midi_device_status;
646 }
647
648 int
649 AlsaAudioBackend::set_midi_option (const std::string& opt)
650 {
651         if (opt != get_standard_device_name(DeviceNone) && opt != _("ALSA raw devices") && opt != _("ALSA sequencer")) {
652                 return -1;
653         }
654         if (_run && _midi_driver_option != opt) {
655                 return -1;
656         }
657         _midi_driver_option = opt;
658         return 0;
659 }
660
661 std::string
662 AlsaAudioBackend::midi_option () const
663 {
664         return _midi_driver_option;
665 }
666
667 int
668 AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable)
669 {
670         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
671         if (!nfo) return -1;
672         const bool prev_enabled = nfo->enabled;
673         nfo->enabled = enable;
674
675         if (_run && prev_enabled != enable) {
676                 // XXX actually we should not change system-ports while running,
677                 // because iterators in main_process_thread will become invalid.
678                 //
679                 // Luckily the engine dialog does not call this while the engine is running,
680                 // This code is currently not used.
681                 if (enable) {
682                         // add ports for the given device
683                         register_system_midi_ports(device);
684                 } else {
685                         // remove all ports provided by the given device
686                         uint32_t i = 0;
687                         for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end ();) {
688                                 assert (_rmidi_out.size() > i);
689                                 AlsaMidiOut *rm = _rmidi_out.at(i);
690                                 if (rm->name () != device) { ++it; ++i; continue; }
691                                 it = _system_midi_out.erase (it);
692                                 unregister_port (*it);
693                                 rm->stop();
694                                 _rmidi_out.erase (_rmidi_out.begin() + i);
695                                 delete rm;
696                         }
697
698                         i = 0;
699                         for (std::vector<AlsaPort*>::iterator it = _system_midi_in.begin (); it != _system_midi_in.end ();) {
700                                 assert (_rmidi_in.size() > i);
701                                 AlsaMidiIn *rm = _rmidi_in.at(i);
702                                 if (rm->name () != device) { ++it; ++i; continue; }
703                                 it = _system_midi_in.erase (it);
704                                 unregister_port (*it);
705                                 rm->stop();
706                                 _rmidi_in.erase (_rmidi_in.begin() + i);
707                                 delete rm;
708                         }
709                 }
710                 update_systemic_midi_latencies ();
711         }
712         return 0;
713 }
714
715 bool
716 AlsaAudioBackend::midi_device_enabled (std::string const device) const
717 {
718         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
719         if (!nfo) return false;
720         return nfo->enabled;
721 }
722
723 /* State Control */
724
725 static void * pthread_process (void *arg)
726 {
727         AlsaAudioBackend *d = static_cast<AlsaAudioBackend *>(arg);
728         d->main_process_thread ();
729         pthread_exit (0);
730         return 0;
731 }
732
733 int
734 AlsaAudioBackend::_start (bool for_latency_measurement)
735 {
736         if (!_active && _run) {
737                 // recover from 'halted', reap threads
738                 stop();
739         }
740
741         if (_active || _run) {
742                 if (for_latency_measurement != _measure_latency) {
743                         _measure_latency = for_latency_measurement;
744                         update_systemic_audio_latencies();
745                         update_systemic_midi_latencies ();
746                         PBD::info << _("AlsaAudioBackend: reload latencies.") << endmsg;
747                         return NoError;
748                 }
749                 PBD::info << _("AlsaAudioBackend: already active.") << endmsg;
750                 return BackendReinitializationError;
751         }
752
753         if (_ports.size () || _portmap.size ()) {
754                 PBD::warning << _("AlsaAudioBackend: recovering from unclean shutdown, port registry is not empty.") << endmsg;
755                 _system_inputs.clear();
756                 _system_outputs.clear();
757                 _system_midi_in.clear();
758                 _system_midi_out.clear();
759                 _ports.clear();
760                 _portmap.clear();
761         }
762
763         /* reset internal state */
764         _dsp_load = 0;
765         _freewheeling = false;
766         _freewheel = false;
767         _last_process_start = 0;
768
769         _device_reservation.release_device();
770
771         assert(_rmidi_in.size() == 0);
772         assert(_rmidi_out.size() == 0);
773         assert(_pcmi == 0);
774
775         int duplex = 0;
776         std::string audio_device;
777         std::string alsa_device;
778         std::map<std::string, std::string> devices;
779
780         if (_input_audio_device == get_standard_device_name(DeviceNone) && _output_audio_device == get_standard_device_name(DeviceNone)) {
781                 PBD::error << _("AlsaAudioBackend: At least one of input or output device needs to be set.");
782                 return AudioDeviceInvalidError;
783         }
784
785         if (_input_audio_device != _output_audio_device) {
786                 if (_input_audio_device != get_standard_device_name(DeviceNone) && _output_audio_device != get_standard_device_name(DeviceNone)) {
787                         PBD::error << _("AlsaAudioBackend: Cannot use two different devices.");
788                         return AudioDeviceInvalidError;
789                 }
790                 if (_input_audio_device != get_standard_device_name(DeviceNone)) {
791                         get_alsa_audio_device_names(devices, HalfDuplexIn);
792                         audio_device = _input_audio_device;
793                         duplex = 1;
794                 } else {
795                         get_alsa_audio_device_names(devices, HalfDuplexOut);
796                         audio_device = _output_audio_device;
797                         duplex = 2;
798                 }
799         } else {
800                 get_alsa_audio_device_names(devices);
801                 audio_device = _input_audio_device;
802                 duplex = 3;
803         }
804
805         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
806                 if (i->first == audio_device) {
807                         alsa_device = i->second;
808                         break;
809                 }
810         }
811         if (alsa_device == "") {
812                 PBD::error << _("AlsaAudioBackend: Cannot find configured device. Is it still connected?");
813                 return AudioDeviceNotAvailableError;
814         }
815
816         _device_reservation.acquire_device(alsa_device.c_str());
817         _pcmi = new Alsa_pcmi (
818                         (duplex & 2) ? alsa_device.c_str() : NULL,
819                         (duplex & 1) ? alsa_device.c_str() : NULL,
820                         /* ctrl name */ 0,
821                         _samplerate, _samples_per_period,
822                         _periods_per_cycle, /* _periods_per_cycle */ 2,
823                         /* debug */ 0);
824
825         AudioBackend::ErrorCode error_code = NoError;
826         switch (_pcmi->state()) {
827         case 0: /* OK */
828                 break;
829         case -1:
830                 PBD::error << _("AlsaAudioBackend: failed to open device.") << endmsg;
831                 error_code = AudioDeviceOpenError;
832                 break;
833         case -2:
834                 PBD::error << _("AlsaAudioBackend: failed to allocate parameters.") << endmsg;
835                 error_code = AudioDeviceOpenError;
836                 break;
837         case -3:
838                 PBD::error << _("AlsaAudioBackend: cannot set requested sample rate.")
839                            << endmsg;
840                 error_code = SampleRateNotSupportedError;
841                 break;
842         case -4:
843                 PBD::error << _("AlsaAudioBackend: cannot set requested period size.")
844                            << endmsg;
845                 error_code = PeriodSizeNotSupportedError;
846                 break;
847         case -5:
848                 PBD::error << _("AlsaAudioBackend: cannot set requested number of periods.")
849                            << endmsg;
850                 error_code = PeriodCountNotSupportedError;
851                 break;
852         case -6:
853                 PBD::error << _("AlsaAudioBackend: unsupported sample format.") << endmsg;
854                 error_code = SampleFormatNotSupportedError;
855                 break;
856         default:
857                 PBD::error << _("AlsaAudioBackend: initialization failed.") << endmsg;
858                 error_code = AudioDeviceOpenError;
859                 break;
860         }
861
862         if (_pcmi->state ()) {
863                 delete _pcmi; _pcmi = 0;
864                 _device_reservation.release_device();
865                 return error_code;
866         }
867
868 #ifndef NDEBUG
869         _pcmi->printinfo ();
870 #endif
871
872         if (_n_outputs != _pcmi->nplay ()) {
873                 if (_n_outputs == 0) {
874                  _n_outputs = _pcmi->nplay ();
875                 } else {
876                  _n_outputs = std::min (_n_outputs, _pcmi->nplay ());
877                 }
878                 PBD::warning << _("AlsaAudioBackend: adjusted output channel count to match device.") << endmsg;
879         }
880
881         if (_n_inputs != _pcmi->ncapt ()) {
882                 if (_n_inputs == 0) {
883                  _n_inputs = _pcmi->ncapt ();
884                 } else {
885                  _n_inputs = std::min (_n_inputs, _pcmi->ncapt ());
886                 }
887                 PBD::warning << _("AlsaAudioBackend: adjusted input channel count to match device.") << endmsg;
888         }
889
890         if (_pcmi->fsize() != _samples_per_period) {
891                 _samples_per_period = _pcmi->fsize();
892                 PBD::warning << _("AlsaAudioBackend: samples per period does not match.") << endmsg;
893         }
894
895         if (_pcmi->fsamp() != _samplerate) {
896                 _samplerate = _pcmi->fsamp();
897                 engine.sample_rate_change (_samplerate);
898                 PBD::warning << _("AlsaAudioBackend: sample rate does not match.") << endmsg;
899         }
900
901         _measure_latency = for_latency_measurement;
902
903         _midi_ins = _midi_outs = 0;
904         register_system_midi_ports();
905
906         if (register_system_audio_ports()) {
907                 PBD::error << _("AlsaAudioBackend: failed to register system ports.") << endmsg;
908                 delete _pcmi; _pcmi = 0;
909                 _device_reservation.release_device();
910                 return PortRegistrationError;
911         }
912
913         engine.sample_rate_change (_samplerate);
914         engine.buffer_size_change (_samples_per_period);
915
916         if (engine.reestablish_ports ()) {
917                 PBD::error << _("AlsaAudioBackend: Could not re-establish ports.") << endmsg;
918                 delete _pcmi; _pcmi = 0;
919                 _device_reservation.release_device();
920                 return PortReconnectError;
921         }
922
923         engine.reconnect_ports ();
924         _run = true;
925         _port_change_flag = false;
926
927         if (pbd_realtime_pthread_create (PBD_SCHED_FIFO, -20, 100000,
928                                 &_main_thread, pthread_process, this))
929         {
930                 if (pthread_create (&_main_thread, NULL, pthread_process, this))
931                 {
932                         PBD::error << _("AlsaAudioBackend: failed to create process thread.") << endmsg;
933                         delete _pcmi; _pcmi = 0;
934                         _device_reservation.release_device();
935                         _run = false;
936                         return ProcessThreadStartError;
937                 } else {
938                         PBD::warning << _("AlsaAudioBackend: cannot acquire realtime permissions.") << endmsg;
939                 }
940         }
941
942         int timeout = 5000;
943         while (!_active && --timeout > 0) { Glib::usleep (1000); }
944
945         if (timeout == 0 || !_active) {
946                 PBD::error << _("AlsaAudioBackend: failed to start process thread.") << endmsg;
947                 delete _pcmi; _pcmi = 0;
948                 _device_reservation.release_device();
949                 _run = false;
950                 return ProcessThreadStartError;
951         }
952
953 #if 1
954         if (NULL != getenv ("ALSAEXT")) {
955                 boost::char_separator<char> sep (";");
956                 boost::tokenizer<boost::char_separator<char> > devs (std::string(getenv ("ALSAEXT")), sep);
957                 BOOST_FOREACH (const std::string& tmp, devs) {
958                         std::string dev (tmp);
959                         std::string::size_type n = dev.find ('@');
960                         unsigned int sr = _samplerate;
961                         unsigned int spp = _samples_per_period;
962                         unsigned int duplex = 3; // TODO parse 1: play, 2: capt, 3:both
963                         if (n != std::string::npos) {
964                                 std::string opt (dev.substr (n + 1));
965                                 sr = PBD::atoi (opt);
966                                 dev = dev.substr (0, n);
967                                 std::string::size_type n = opt.find ('/');
968                                 if (n != std::string::npos) {
969                                         spp = PBD::atoi (opt.substr (n + 1));
970                                 }
971                         }
972                         if (add_slave (dev.c_str(), sr, spp, duplex)) {
973                                 PBD::info << string_compose (_("ALSA slave '%1' added"), dev) << endmsg;
974                         } else {
975                                 PBD::error << string_compose (_("ALSA failed to add '%1' as slave"), dev) << endmsg;
976                         }
977                 }
978         }
979 #endif
980
981         return NoError;
982 }
983
984 int
985 AlsaAudioBackend::stop ()
986 {
987         void *status;
988         if (!_run) {
989                 return 0;
990         }
991
992         _run = false;
993         if (pthread_join (_main_thread, &status)) {
994                 PBD::error << _("AlsaAudioBackend: failed to terminate.") << endmsg;
995                 return -1;
996         }
997
998         while (!_rmidi_out.empty ()) {
999                 AlsaMidiIO *m = _rmidi_out.back ();
1000                 m->stop();
1001                 _rmidi_out.pop_back ();
1002                 delete m;
1003         }
1004         while (!_rmidi_in.empty ()) {
1005                 AlsaMidiIO *m = _rmidi_in.back ();
1006                 m->stop();
1007                 _rmidi_in.pop_back ();
1008                 delete m;
1009         }
1010
1011         while (!_slaves.empty ()) {
1012                 AudioSlave* s = _slaves.back ();
1013                 _slaves.pop_back ();
1014                 delete s;
1015         }
1016
1017         unregister_ports();
1018         delete _pcmi; _pcmi = 0;
1019         _midi_ins = _midi_outs = 0;
1020         _device_reservation.release_device();
1021         _measure_latency = false;
1022
1023         return (_active == false) ? 0 : -1;
1024 }
1025
1026 int
1027 AlsaAudioBackend::freewheel (bool onoff)
1028 {
1029         _freewheeling = onoff;
1030         return 0;
1031 }
1032
1033 float
1034 AlsaAudioBackend::dsp_load () const
1035 {
1036         return 100.f * _dsp_load;
1037 }
1038
1039 size_t
1040 AlsaAudioBackend::raw_buffer_size (DataType t)
1041 {
1042         switch (t) {
1043                 case DataType::AUDIO:
1044                         return _samples_per_period * sizeof(Sample);
1045                 case DataType::MIDI:
1046                         return _max_buffer_size; // XXX not really limited
1047         }
1048         return 0;
1049 }
1050
1051 /* Process time */
1052 samplepos_t
1053 AlsaAudioBackend::sample_time ()
1054 {
1055         return _processed_samples;
1056 }
1057
1058 samplepos_t
1059 AlsaAudioBackend::sample_time_at_cycle_start ()
1060 {
1061         return _processed_samples;
1062 }
1063
1064 pframes_t
1065 AlsaAudioBackend::samples_since_cycle_start ()
1066 {
1067         if (!_active || !_run || _freewheeling || _freewheel) {
1068                 return 0;
1069         }
1070         if (_last_process_start == 0) {
1071                 return 0;
1072         }
1073
1074         const int64_t elapsed_time_us = g_get_monotonic_time() - _last_process_start;
1075         return std::max((pframes_t)0, (pframes_t)rint(1e-6 * elapsed_time_us * _samplerate));
1076 }
1077
1078
1079 void *
1080 AlsaAudioBackend::alsa_process_thread (void *arg)
1081 {
1082         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
1083         boost::function<void ()> f = td->f;
1084         delete td;
1085         f ();
1086         return 0;
1087 }
1088
1089 int
1090 AlsaAudioBackend::create_process_thread (boost::function<void()> func)
1091 {
1092         pthread_t thread_id;
1093         pthread_attr_t attr;
1094         size_t stacksize = 100000;
1095
1096         ThreadData* td = new ThreadData (this, func, stacksize);
1097
1098         if (pbd_realtime_pthread_create (PBD_SCHED_FIFO, -22, stacksize,
1099                                 &thread_id, alsa_process_thread, td)) {
1100                 pthread_attr_init (&attr);
1101                 pthread_attr_setstacksize (&attr, stacksize);
1102                 if (pthread_create (&thread_id, &attr, alsa_process_thread, td)) {
1103                         PBD::error << _("AudioEngine: cannot create process thread.") << endmsg;
1104                         pthread_attr_destroy (&attr);
1105                         return -1;
1106                 }
1107                 pthread_attr_destroy (&attr);
1108         }
1109
1110         _threads.push_back (thread_id);
1111         return 0;
1112 }
1113
1114 int
1115 AlsaAudioBackend::join_process_threads ()
1116 {
1117         int rv = 0;
1118
1119         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
1120         {
1121                 void *status;
1122                 if (pthread_join (*i, &status)) {
1123                         PBD::error << _("AudioEngine: cannot terminate process thread.") << endmsg;
1124                         rv -= 1;
1125                 }
1126         }
1127         _threads.clear ();
1128         return rv;
1129 }
1130
1131 bool
1132 AlsaAudioBackend::in_process_thread ()
1133 {
1134         if (pthread_equal (_main_thread, pthread_self()) != 0) {
1135                 return true;
1136         }
1137
1138         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
1139         {
1140                 if (pthread_equal (*i, pthread_self ()) != 0) {
1141                         return true;
1142                 }
1143         }
1144         return false;
1145 }
1146
1147 uint32_t
1148 AlsaAudioBackend::process_thread_count ()
1149 {
1150         return _threads.size ();
1151 }
1152
1153 void
1154 AlsaAudioBackend::update_latencies ()
1155 {
1156         // trigger latency callback in RT thread (locked graph)
1157         port_connect_add_remove_callback();
1158 }
1159
1160 /* PORTENGINE API */
1161
1162 void*
1163 AlsaAudioBackend::private_handle () const
1164 {
1165         return NULL;
1166 }
1167
1168 const std::string&
1169 AlsaAudioBackend::my_name () const
1170 {
1171         return _instance_name;
1172 }
1173
1174 bool
1175 AlsaAudioBackend::available () const
1176 {
1177         return _run && _active;
1178 }
1179
1180 uint32_t
1181 AlsaAudioBackend::port_name_size () const
1182 {
1183         return 256;
1184 }
1185
1186 int
1187 AlsaAudioBackend::set_port_name (PortEngine::PortHandle port, const std::string& name)
1188 {
1189         std::string newname (_instance_name + ":" + name);
1190         if (!valid_port (port)) {
1191                 PBD::error << _("AlsaBackend::set_port_name: Invalid Port") << endmsg;
1192                 return -1;
1193         }
1194         if (find_port (newname)) {
1195                 PBD::error << _("AlsaBackend::set_port_name: Port with given name already exists") << endmsg;
1196                 return -1;
1197         }
1198
1199         AlsaPort* p = static_cast<AlsaPort*>(port);
1200         _portmap.erase (p->name());
1201         _portmap.insert (make_pair (newname, p));
1202         return p->set_name (newname);
1203 }
1204
1205 std::string
1206 AlsaAudioBackend::get_port_name (PortEngine::PortHandle port) const
1207 {
1208         if (!valid_port (port)) {
1209                 PBD::warning << _("AlsaBackend::get_port_name: Invalid Port(s)") << endmsg;
1210                 return std::string ();
1211         }
1212         return static_cast<AlsaPort*>(port)->name ();
1213 }
1214
1215 int
1216 AlsaAudioBackend::get_port_property (PortHandle port, const std::string& key, std::string& value, std::string& type) const
1217 {
1218         if (!valid_port (port)) {
1219                 PBD::warning << _("AlsaBackend::get_port_property: Invalid Port(s)") << endmsg;
1220                 return -1;
1221         }
1222         if (key == "http://jackaudio.org/metadata/pretty-name") {
1223                 type = "";
1224                 value = static_cast<AlsaPort*>(port)->pretty_name ();
1225                 if (!value.empty()) {
1226                         return 0;
1227                 }
1228         }
1229         return -1;
1230 }
1231
1232 int
1233 AlsaAudioBackend::set_port_property (PortHandle port, const std::string& key, const std::string& value, const std::string& type)
1234 {
1235         if (!valid_port (port)) {
1236                 PBD::warning << _("AlsaBackend::set_port_property: Invalid Port(s)") << endmsg;
1237                 return -1;
1238         }
1239         if (key == "http://jackaudio.org/metadata/pretty-name" && type.empty ()) {
1240                 static_cast<AlsaPort*>(port)->set_pretty_name (value);
1241                 return 0;
1242         }
1243         return -1;
1244 }
1245
1246 PortEngine::PortHandle
1247 AlsaAudioBackend::get_port_by_name (const std::string& name) const
1248 {
1249         PortHandle port = (PortHandle) find_port (name);
1250         return port;
1251 }
1252
1253 int
1254 AlsaAudioBackend::get_ports (
1255                 const std::string& port_name_pattern,
1256                 DataType type, PortFlags flags,
1257                 std::vector<std::string>& port_names) const
1258 {
1259         int rv = 0;
1260         regex_t port_regex;
1261         bool use_regexp = false;
1262         if (port_name_pattern.size () > 0) {
1263                 if (!regcomp (&port_regex, port_name_pattern.c_str (), REG_EXTENDED|REG_NOSUB)) {
1264                         use_regexp = true;
1265                 }
1266         }
1267
1268         for (PortIndex::const_iterator i = _ports.begin (); i != _ports.end (); ++i) {
1269                 AlsaPort* port = *i;
1270                 if ((port->type () == type) && flags == (port->flags () & flags)) {
1271                         if (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) {
1272                                 port_names.push_back (port->name ());
1273                                 ++rv;
1274                         }
1275                 }
1276         }
1277         if (use_regexp) {
1278                 regfree (&port_regex);
1279         }
1280         return rv;
1281 }
1282
1283 DataType
1284 AlsaAudioBackend::port_data_type (PortEngine::PortHandle port) const
1285 {
1286         if (!valid_port (port)) {
1287                 return DataType::NIL;
1288         }
1289         return static_cast<AlsaPort*>(port)->type ();
1290 }
1291
1292 PortEngine::PortHandle
1293 AlsaAudioBackend::register_port (
1294                 const std::string& name,
1295                 ARDOUR::DataType type,
1296                 ARDOUR::PortFlags flags)
1297 {
1298         if (name.size () == 0) { return 0; }
1299         if (flags & IsPhysical) { return 0; }
1300         return add_port (_instance_name + ":" + name, type, flags);
1301 }
1302
1303 PortEngine::PortHandle
1304 AlsaAudioBackend::add_port (
1305                 const std::string& name,
1306                 ARDOUR::DataType type,
1307                 ARDOUR::PortFlags flags)
1308 {
1309         assert(name.size ());
1310         if (find_port (name)) {
1311                 PBD::error << _("AlsaBackend::register_port: Port already exists:")
1312                                 << " (" << name << ")" << endmsg;
1313                 return 0;
1314         }
1315         AlsaPort* port = NULL;
1316         switch (type) {
1317                 case DataType::AUDIO:
1318                         port = new AlsaAudioPort (*this, name, flags);
1319                         break;
1320                 case DataType::MIDI:
1321                         port = new AlsaMidiPort (*this, name, flags);
1322                         break;
1323                 default:
1324                         PBD::error << _("AlsaBackend::register_port: Invalid Data Type.") << endmsg;
1325                         return 0;
1326         }
1327
1328         _ports.insert (port);
1329         _portmap.insert (make_pair (name, port));
1330
1331         return port;
1332 }
1333
1334 void
1335 AlsaAudioBackend::unregister_port (PortEngine::PortHandle port_handle)
1336 {
1337         if (!_run) {
1338                 return;
1339         }
1340         AlsaPort* port = static_cast<AlsaPort*>(port_handle);
1341         PortIndex::iterator i = std::find (_ports.begin(), _ports.end(), static_cast<AlsaPort*>(port_handle));
1342         if (i == _ports.end ()) {
1343                 PBD::error << _("AlsaBackend::unregister_port: Failed to find port") << endmsg;
1344                 return;
1345         }
1346         disconnect_all(port_handle);
1347         _portmap.erase (port->name());
1348         _ports.erase (i);
1349         delete port;
1350 }
1351
1352 int
1353 AlsaAudioBackend::register_system_audio_ports()
1354 {
1355         LatencyRange lr;
1356
1357         const int a_ins = _n_inputs;
1358         const int a_out = _n_outputs;
1359
1360         const uint32_t lcpp = (_periods_per_cycle - 2) * _samples_per_period;
1361
1362         /* audio ports */
1363         lr.min = lr.max = (_systemic_audio_input_latency);
1364         for (int i = 1; i <= a_ins; ++i) {
1365                 char tmp[64];
1366                 snprintf(tmp, sizeof(tmp), "system:capture_%d", i);
1367                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
1368                 if (!p) return -1;
1369                 set_latency_range (p, false, lr);
1370                 AlsaPort *ap = static_cast<AlsaPort*>(p);
1371                 //ap->set_pretty_name ("")
1372                 _system_inputs.push_back (ap);
1373         }
1374
1375         lr.min = lr.max = lcpp + (_systemic_audio_output_latency);
1376         for (int i = 1; i <= a_out; ++i) {
1377                 char tmp[64];
1378                 snprintf(tmp, sizeof(tmp), "system:playback_%d", i);
1379                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
1380                 if (!p) return -1;
1381                 set_latency_range (p, true, lr);
1382                 AlsaPort *ap = static_cast<AlsaPort*>(p);
1383                 //ap->set_pretty_name ("")
1384                 _system_outputs.push_back (ap);
1385         }
1386         return 0;
1387 }
1388
1389 /* set playback-latency for _system_inputs
1390  * and capture-latency for _system_outputs
1391  */
1392 void
1393 AlsaAudioBackend::update_system_port_latecies ()
1394 {
1395         for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
1396                 (*it)->update_connected_latency (true);
1397         }
1398         for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
1399                 (*it)->update_connected_latency (false);
1400         }
1401
1402         for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
1403                 (*it)->update_connected_latency (true);
1404         }
1405         for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
1406                 (*it)->update_connected_latency (false);
1407         }
1408
1409         for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) {
1410                 if ((*s)->dead) {
1411                         continue;
1412                 }
1413                 for (std::vector<AlsaPort*>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it) {
1414                         (*it)->update_connected_latency (true);
1415                 }
1416                 for (std::vector<AlsaPort*>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it) {
1417                         (*it)->update_connected_latency (false);
1418                 }
1419         }
1420 }
1421
1422 /* libs/ardouralsautil/devicelist.cc appends either of
1423  * " (IO)", " (I)", or " (O)"
1424  * depending of the device is full-duples or half-duplex
1425  */
1426 static std::string replace_name_io (std::string const& name, bool in)
1427 {
1428         if (name.empty ()) {
1429                 return "";
1430         }
1431         size_t pos = name.find_last_of ('(');
1432         if (pos == std::string::npos) {
1433                 assert (0); // this should never happen.
1434                 return name;
1435         }
1436         return name.substr (0, pos) + "(" + (in ? "In" : "Out") + ")";
1437 }
1438
1439 int
1440 AlsaAudioBackend::register_system_midi_ports(const std::string device)
1441 {
1442         std::map<std::string, std::string> devices;
1443
1444         // TODO use consistent numbering when re-adding devices: _midi_ins, _midi_outs
1445
1446         if (_midi_driver_option == get_standard_device_name(DeviceNone)) {
1447                 return 0;
1448         } else if (_midi_driver_option == _("ALSA raw devices")) {
1449                 get_alsa_rawmidi_device_names(devices);
1450         } else {
1451                 get_alsa_sequencer_names (devices);
1452         }
1453
1454         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
1455                 if (!device.empty() && device != i->first) {
1456                         continue;
1457                 }
1458                 struct AlsaMidiDeviceInfo * nfo = midi_device_info(i->first);
1459                 if (!nfo) continue;
1460                 if (!nfo->enabled) continue;
1461
1462                 AlsaMidiOut *mout;
1463                 if (_midi_driver_option == _("ALSA raw devices")) {
1464                         mout = new AlsaRawMidiOut (i->first, i->second.c_str());
1465                 } else {
1466                         mout = new AlsaSeqMidiOut (i->first, i->second.c_str());
1467                 }
1468
1469                 if (mout->state ()) {
1470                         PBD::warning << string_compose (
1471                                         _("AlsaMidiOut: failed to open midi device '%1'."), i->second)
1472                                 << endmsg;
1473                         delete mout;
1474                 } else {
1475                         mout->setup_timing(_samples_per_period, _samplerate);
1476                         mout->sync_time (g_get_monotonic_time());
1477                         if (mout->start ()) {
1478                                 PBD::warning << string_compose (
1479                                                 _("AlsaMidiOut: failed to start midi device '%1'."), i->second)
1480                                         << endmsg;
1481                                 delete mout;
1482                         } else {
1483                                 char tmp[64];
1484                                 snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++_midi_ins);
1485                                 PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
1486                                 if (!p) {
1487                                         mout->stop();
1488                                         delete mout;
1489                                 }
1490                                 LatencyRange lr;
1491                                 lr.min = lr.max = (nfo->systemic_output_latency);
1492                                 set_latency_range (p, true, lr);
1493                                 static_cast<AlsaMidiPort*>(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment
1494                                 AlsaPort *ap = static_cast<AlsaPort*>(p);
1495                                 ap->set_pretty_name (replace_name_io (i->first, false));
1496                                 _system_midi_out.push_back (ap);
1497                                 _rmidi_out.push_back (mout);
1498                         }
1499                 }
1500
1501                 AlsaMidiIn *midin;
1502                 if (_midi_driver_option == _("ALSA raw devices")) {
1503                         midin = new AlsaRawMidiIn (i->first, i->second.c_str());
1504                 } else {
1505                         midin = new AlsaSeqMidiIn (i->first, i->second.c_str());
1506                 }
1507
1508                 if (midin->state ()) {
1509                         PBD::warning << string_compose (
1510                                         _("AlsaMidiIn: failed to open midi device '%1'."), i->second)
1511                                 << endmsg;
1512                         delete midin;
1513                 } else {
1514                         midin->setup_timing(_samples_per_period, _samplerate);
1515                         midin->sync_time (g_get_monotonic_time());
1516                         if (midin->start ()) {
1517                                 PBD::warning << string_compose (
1518                                                 _("AlsaMidiIn: failed to start midi device '%1'."), i->second)
1519                                         << endmsg;
1520                                 delete midin;
1521                         } else {
1522                                 char tmp[64];
1523                                 snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++_midi_outs);
1524                                 PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
1525                                 if (!p) {
1526                                         midin->stop();
1527                                         delete midin;
1528                                         continue;
1529                                 }
1530                                 LatencyRange lr;
1531                                 lr.min = lr.max = (nfo->systemic_input_latency);
1532                                 set_latency_range (p, false, lr);
1533                                 AlsaPort *ap = static_cast<AlsaPort*>(p);
1534                                 ap->set_pretty_name (replace_name_io (i->first, true));
1535                                 _system_midi_in.push_back (ap);
1536                                 _rmidi_in.push_back (midin);
1537                         }
1538                 }
1539         }
1540         return 0;
1541 }
1542
1543 void
1544 AlsaAudioBackend::unregister_ports (bool system_only)
1545 {
1546         _system_inputs.clear();
1547         _system_outputs.clear();
1548         _system_midi_in.clear();
1549         _system_midi_out.clear();
1550
1551         for (PortIndex::iterator i = _ports.begin (); i != _ports.end ();) {
1552                 PortIndex::iterator cur = i++;
1553                 AlsaPort* port = *cur;
1554                 if (! system_only || (port->is_physical () && port->is_terminal ())) {
1555                         port->disconnect_all ();
1556                         _portmap.erase (port->name());
1557                         delete port;
1558                         _ports.erase (cur);
1559                 }
1560         }
1561 }
1562
1563 int
1564 AlsaAudioBackend::connect (const std::string& src, const std::string& dst)
1565 {
1566         AlsaPort* src_port = find_port (src);
1567         AlsaPort* dst_port = find_port (dst);
1568
1569         if (!src_port) {
1570                 PBD::error << _("AlsaBackend::connect: Invalid Source port:")
1571                                 << " (" << src <<")" << endmsg;
1572                 return -1;
1573         }
1574         if (!dst_port) {
1575                 PBD::error << _("AlsaBackend::connect: Invalid Destination port:")
1576                         << " (" << dst <<")" << endmsg;
1577                 return -1;
1578         }
1579         return src_port->connect (dst_port);
1580 }
1581
1582 int
1583 AlsaAudioBackend::disconnect (const std::string& src, const std::string& dst)
1584 {
1585         AlsaPort* src_port = find_port (src);
1586         AlsaPort* dst_port = find_port (dst);
1587
1588         if (!src_port || !dst_port) {
1589                 PBD::error << _("AlsaBackend::disconnect: Invalid Port(s)") << endmsg;
1590                 return -1;
1591         }
1592         return src_port->disconnect (dst_port);
1593 }
1594
1595 int
1596 AlsaAudioBackend::connect (PortEngine::PortHandle src, const std::string& dst)
1597 {
1598         AlsaPort* dst_port = find_port (dst);
1599         if (!valid_port (src)) {
1600                 PBD::error << _("AlsaBackend::connect: Invalid Source Port Handle") << endmsg;
1601                 return -1;
1602         }
1603         if (!dst_port) {
1604                 PBD::error << _("AlsaBackend::connect: Invalid Destination Port")
1605                         << " (" << dst << ")" << endmsg;
1606                 return -1;
1607         }
1608         return static_cast<AlsaPort*>(src)->connect (dst_port);
1609 }
1610
1611 int
1612 AlsaAudioBackend::disconnect (PortEngine::PortHandle src, const std::string& dst)
1613 {
1614         AlsaPort* dst_port = find_port (dst);
1615         if (!valid_port (src) || !dst_port) {
1616                 PBD::error << _("AlsaBackend::disconnect: Invalid Port(s)") << endmsg;
1617                 return -1;
1618         }
1619         return static_cast<AlsaPort*>(src)->disconnect (dst_port);
1620 }
1621
1622 int
1623 AlsaAudioBackend::disconnect_all (PortEngine::PortHandle port)
1624 {
1625         if (!valid_port (port)) {
1626                 PBD::error << _("AlsaBackend::disconnect_all: Invalid Port") << endmsg;
1627                 return -1;
1628         }
1629         static_cast<AlsaPort*>(port)->disconnect_all ();
1630         return 0;
1631 }
1632
1633 bool
1634 AlsaAudioBackend::connected (PortEngine::PortHandle port, bool /* process_callback_safe*/)
1635 {
1636         if (!valid_port (port)) {
1637                 PBD::error << _("AlsaBackend::disconnect_all: Invalid Port") << endmsg;
1638                 return false;
1639         }
1640         return static_cast<AlsaPort*>(port)->is_connected ();
1641 }
1642
1643 bool
1644 AlsaAudioBackend::connected_to (PortEngine::PortHandle src, const std::string& dst, bool /*process_callback_safe*/)
1645 {
1646         AlsaPort* dst_port = find_port (dst);
1647 #ifndef NDEBUG
1648         if (!valid_port (src) || !dst_port) {
1649                 PBD::error << _("AlsaBackend::connected_to: Invalid Port") << endmsg;
1650                 return false;
1651         }
1652 #endif
1653         return static_cast<AlsaPort*>(src)->is_connected (dst_port);
1654 }
1655
1656 bool
1657 AlsaAudioBackend::physically_connected (PortEngine::PortHandle port, bool /*process_callback_safe*/)
1658 {
1659         if (!valid_port (port)) {
1660                 PBD::error << _("AlsaBackend::physically_connected: Invalid Port") << endmsg;
1661                 return false;
1662         }
1663         return static_cast<AlsaPort*>(port)->is_physically_connected ();
1664 }
1665
1666 int
1667 AlsaAudioBackend::get_connections (PortEngine::PortHandle port, std::vector<std::string>& names, bool /*process_callback_safe*/)
1668 {
1669         if (!valid_port (port)) {
1670                 PBD::error << _("AlsaBackend::get_connections: Invalid Port") << endmsg;
1671                 return -1;
1672         }
1673
1674         assert (0 == names.size ());
1675
1676         const std::set<AlsaPort*>& connected_ports = static_cast<AlsaPort*>(port)->get_connections ();
1677
1678         for (std::set<AlsaPort*>::const_iterator i = connected_ports.begin (); i != connected_ports.end (); ++i) {
1679                 names.push_back ((*i)->name ());
1680         }
1681
1682         return (int)names.size ();
1683 }
1684
1685 /* MIDI */
1686 int
1687 AlsaAudioBackend::midi_event_get (
1688                 pframes_t& timestamp,
1689                 size_t& size, uint8_t const** buf, void* port_buffer,
1690                 uint32_t event_index)
1691 {
1692         assert (buf && port_buffer);
1693         AlsaMidiBuffer& source = * static_cast<AlsaMidiBuffer*>(port_buffer);
1694         if (event_index >= source.size ()) {
1695                 return -1;
1696         }
1697         AlsaMidiEvent const& event = source[event_index];
1698
1699         timestamp = event.timestamp ();
1700         size = event.size ();
1701         *buf = event.data ();
1702         return 0;
1703 }
1704
1705 int
1706 AlsaAudioBackend::midi_event_put (
1707                 void* port_buffer,
1708                 pframes_t timestamp,
1709                 const uint8_t* buffer, size_t size)
1710 {
1711         assert (buffer && port_buffer);
1712         if (size >= MaxAlsaMidiEventSize) {
1713                 return -1;
1714         }
1715         AlsaMidiBuffer& dst = * static_cast<AlsaMidiBuffer*>(port_buffer);
1716 #ifndef NDEBUG
1717         if (dst.size () && (pframes_t)dst.back ().timestamp () > timestamp) {
1718                 // nevermind, ::get_buffer() sorts events
1719                 fprintf (stderr, "AlsaMidiBuffer: it's too late for this event. %d > %d\n",
1720                                 (pframes_t)dst.back ().timestamp (), timestamp);
1721         }
1722 #endif
1723         dst.push_back (AlsaMidiEvent (timestamp, buffer, size));
1724         return 0;
1725 }
1726
1727 uint32_t
1728 AlsaAudioBackend::get_midi_event_count (void* port_buffer)
1729 {
1730         assert (port_buffer);
1731         return static_cast<AlsaMidiBuffer*>(port_buffer)->size ();
1732 }
1733
1734 void
1735 AlsaAudioBackend::midi_clear (void* port_buffer)
1736 {
1737         assert (port_buffer);
1738         AlsaMidiBuffer * buf = static_cast<AlsaMidiBuffer*>(port_buffer);
1739         assert (buf);
1740         buf->clear ();
1741 }
1742
1743 /* Monitoring */
1744
1745 bool
1746 AlsaAudioBackend::can_monitor_input () const
1747 {
1748         return false;
1749 }
1750
1751 int
1752 AlsaAudioBackend::request_input_monitoring (PortEngine::PortHandle, bool)
1753 {
1754         return -1;
1755 }
1756
1757 int
1758 AlsaAudioBackend::ensure_input_monitoring (PortEngine::PortHandle, bool)
1759 {
1760         return -1;
1761 }
1762
1763 bool
1764 AlsaAudioBackend::monitoring_input (PortEngine::PortHandle)
1765 {
1766         return false;
1767 }
1768
1769 /* Latency management */
1770
1771 void
1772 AlsaAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range)
1773 {
1774         if (!valid_port (port)) {
1775                 PBD::error << _("AlsaPort::set_latency_range (): invalid port.") << endmsg;
1776         }
1777         static_cast<AlsaPort*>(port)->set_latency_range (latency_range, for_playback);
1778 }
1779
1780 LatencyRange
1781 AlsaAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback)
1782 {
1783         LatencyRange r;
1784         if (!valid_port (port)) {
1785                 PBD::error << _("AlsaPort::get_latency_range (): invalid port.") << endmsg;
1786                 r.min = 0;
1787                 r.max = 0;
1788                 return r;
1789         }
1790         AlsaPort *p = static_cast<AlsaPort*>(port);
1791         assert(p);
1792
1793         r = p->latency_range (for_playback);
1794         if (p->is_physical() && p->is_terminal()) {
1795                 if (p->is_input() && for_playback) {
1796                         r.min += _samples_per_period;
1797                         r.max += _samples_per_period;
1798                 }
1799                 if (p->is_output() && !for_playback) {
1800                         r.min += _samples_per_period;
1801                         r.max += _samples_per_period;
1802                 }
1803         }
1804         return r;
1805 }
1806
1807 /* Discovering physical ports */
1808
1809 bool
1810 AlsaAudioBackend::port_is_physical (PortEngine::PortHandle port) const
1811 {
1812         if (!valid_port (port)) {
1813                 PBD::error << _("AlsaPort::port_is_physical (): invalid port.") << endmsg;
1814                 return false;
1815         }
1816         return static_cast<AlsaPort*>(port)->is_physical ();
1817 }
1818
1819 void
1820 AlsaAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>& port_names)
1821 {
1822         for (PortIndex::iterator i = _ports.begin (); i != _ports.end (); ++i) {
1823                 AlsaPort* port = *i;
1824                 if ((port->type () == type) && port->is_input () && port->is_physical ()) {
1825                         port_names.push_back (port->name ());
1826                 }
1827         }
1828 }
1829
1830 void
1831 AlsaAudioBackend::get_physical_inputs (DataType type, std::vector<std::string>& port_names)
1832 {
1833         for (PortIndex::iterator i = _ports.begin (); i != _ports.end (); ++i) {
1834                 AlsaPort* port = *i;
1835                 if ((port->type () == type) && port->is_output () && port->is_physical ()) {
1836                         port_names.push_back (port->name ());
1837                 }
1838         }
1839 }
1840
1841 ChanCount
1842 AlsaAudioBackend::n_physical_outputs () const
1843 {
1844         int n_midi = 0;
1845         int n_audio = 0;
1846         for (PortIndex::const_iterator i = _ports.begin (); i != _ports.end (); ++i) {
1847                 AlsaPort* port = *i;
1848                 if (port->is_output () && port->is_physical ()) {
1849                         switch (port->type ()) {
1850                                 case DataType::AUDIO: ++n_audio; break;
1851                                 case DataType::MIDI: ++n_midi; break;
1852                                 default: break;
1853                         }
1854                 }
1855         }
1856         ChanCount cc;
1857         cc.set (DataType::AUDIO, n_audio);
1858         cc.set (DataType::MIDI, n_midi);
1859         return cc;
1860 }
1861
1862 ChanCount
1863 AlsaAudioBackend::n_physical_inputs () const
1864 {
1865         int n_midi = 0;
1866         int n_audio = 0;
1867         for (PortIndex::const_iterator i = _ports.begin (); i != _ports.end (); ++i) {
1868                 AlsaPort* port = *i;
1869                 if (port->is_input () && port->is_physical ()) {
1870                         switch (port->type ()) {
1871                                 case DataType::AUDIO: ++n_audio; break;
1872                                 case DataType::MIDI: ++n_midi; break;
1873                                 default: break;
1874                         }
1875                 }
1876         }
1877         ChanCount cc;
1878         cc.set (DataType::AUDIO, n_audio);
1879         cc.set (DataType::MIDI, n_midi);
1880         return cc;
1881 }
1882
1883 /* Getting access to the data buffer for a port */
1884
1885 void*
1886 AlsaAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes)
1887 {
1888         assert (port);
1889         assert (valid_port (port));
1890         return static_cast<AlsaPort*>(port)->get_buffer (nframes);
1891 }
1892
1893 /* Engine Process */
1894 void *
1895 AlsaAudioBackend::main_process_thread ()
1896 {
1897         AudioEngine::thread_init_callback (this);
1898         _active = true;
1899         bool reset_dll = true;
1900         int last_n_periods = 0;
1901         _processed_samples = 0;
1902
1903         double dll_dt = (double) _samples_per_period / (double) _samplerate;
1904         double dll_w1 = 2 * M_PI * 0.1 * dll_dt;
1905         double dll_w2 = dll_w1 * dll_w1;
1906
1907         uint64_t clock1;
1908         _pcmi->pcm_start ();
1909         int no_proc_errors = 0;
1910         const int bailout = 5 * _samplerate / _samples_per_period;
1911
1912         manager.registration_callback();
1913         manager.graph_order_callback();
1914
1915         const double sr_norm = 1e-6 * (double) _samplerate / (double)_samples_per_period;
1916
1917         while (_run) {
1918                 long nr;
1919                 bool xrun = false;
1920                 bool drain_slaves = false;
1921
1922                 if (_freewheeling != _freewheel) {
1923                         _freewheel = _freewheeling;
1924                         engine.freewheel_callback (_freewheel);
1925                         for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) {
1926                                 (*s)->freewheel (_freewheel);
1927                         }
1928                         if (!_freewheel) {
1929                                 _pcmi->pcm_stop ();
1930                                 _pcmi->pcm_start ();
1931                                 drain_slaves = true;
1932                         }
1933                 }
1934
1935                 if (!_freewheel) {
1936                         nr = _pcmi->pcm_wait ();
1937
1938                         /* update DLL */
1939                         uint64_t clock0 = g_get_monotonic_time();
1940                         if (reset_dll || last_n_periods != 1) {
1941                                 reset_dll = false;
1942                                 drain_slaves = true;
1943                                 dll_dt = 1e6 * (double) _samples_per_period / (double)_samplerate;
1944                                 _t0 = clock0;
1945                                 _t1 = clock0 + dll_dt;
1946                         } else {
1947                                 const double er = clock0 - _t1;
1948                                 _t0 = _t1;
1949                                 _t1 = _t1 + dll_w1 * er + dll_dt;
1950                                 dll_dt += dll_w2 * er;
1951                         }
1952
1953                         for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) {
1954                                 if ((*s)->dead) {
1955                                         continue;
1956                                 }
1957                                 if ((*s)->halt) {
1958                                         /* slave died, unregister its ports (not rt-safe, but no matter) */
1959                                         PBD::error << _("ALSA Slave device halted") << endmsg;
1960                                         for (std::vector<AlsaPort*>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it) {
1961                                                 unregister_port (*it);
1962                                         }
1963                                         for (std::vector<AlsaPort*>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it) {
1964                                                 unregister_port (*it);
1965                                         }
1966                                         (*s)->inputs.clear ();
1967                                         (*s)->outputs.clear ();
1968                                         (*s)->active = false;
1969                                         (*s)->dead = true;
1970                                         continue;
1971                                 }
1972                                 (*s)->active = (*s)->running () && (*s)->state () >= 0;
1973                                 if (!(*s)->active) {
1974                                         continue;
1975                                 }
1976                                 (*s)->cycle_start (_t0, (_t1 - _t0) * sr_norm, drain_slaves);
1977                         }
1978
1979                         if (_pcmi->state () > 0) {
1980                                 ++no_proc_errors;
1981                                 xrun = true;
1982                         }
1983                         if (_pcmi->state () < 0) {
1984                                 PBD::error << _("AlsaAudioBackend: I/O error. Audio Process Terminated.") << endmsg;
1985                                 break;
1986                         }
1987                         if (no_proc_errors > bailout) {
1988                                 PBD::error
1989                                         << string_compose (
1990                                                         _("AlsaAudioBackend: Audio Process Terminated after %1 consecutive x-runs."),
1991                                                         no_proc_errors)
1992                                         << endmsg;
1993                                 break;
1994                         }
1995
1996                         last_n_periods = 0;
1997                         while (nr >= (long)_samples_per_period && _freewheeling == _freewheel) {
1998                                 uint32_t i = 0;
1999                                 clock1 = g_get_monotonic_time();
2000                                 no_proc_errors = 0;
2001
2002                                 _pcmi->capt_init (_samples_per_period);
2003                                 for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++i) {
2004                                         _pcmi->capt_chan (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period);
2005                                 }
2006                                 _pcmi->capt_done (_samples_per_period);
2007
2008                                 for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) {
2009                                         if (!(*s)->active) {
2010                                                 continue;
2011                                         }
2012                                         i = 0;
2013                                         for (std::vector<AlsaPort*>::const_iterator it = (*s)->inputs.begin (); it != (*s)->inputs.end (); ++it, ++i) {
2014                                                 (*s)->capt_chan (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period);
2015                                         }
2016                                 }
2017
2018                                 /* de-queue incoming midi*/
2019                                 i = 0;
2020                                 for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
2021                                         assert (_rmidi_in.size() > i);
2022                                         AlsaMidiIn *rm = _rmidi_in.at(i);
2023                                         void *bptr = (*it)->get_buffer(0);
2024                                         pframes_t time;
2025                                         uint8_t data[MaxAlsaMidiEventSize];
2026                                         size_t size = sizeof(data);
2027                                         midi_clear(bptr);
2028                                         while (rm->recv_event (time, data, size)) {
2029                                                 midi_event_put(bptr, time, data, size);
2030                                                 size = sizeof(data);
2031                                         }
2032                                         rm->sync_time (clock1);
2033                                 }
2034
2035                                 for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
2036                                         memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
2037                                 }
2038
2039                                 /* call engine process callback */
2040                                 _last_process_start = g_get_monotonic_time();
2041                                 if (engine.process_callback (_samples_per_period)) {
2042                                         _pcmi->pcm_stop ();
2043                                         _active = false;
2044                                         return 0;
2045                                 }
2046
2047                                 for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
2048                                         static_cast<AlsaMidiPort*>(*it)->next_period();
2049                                 }
2050
2051                                 /* queue outgoing midi */
2052                                 i = 0;
2053                                 for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
2054                                         assert (_rmidi_out.size() > i);
2055                                         const AlsaMidiBuffer * src = static_cast<const AlsaMidiPort*>(*it)->const_buffer();
2056                                         AlsaMidiOut *rm = _rmidi_out.at(i);
2057                                         rm->sync_time (clock1);
2058                                         for (AlsaMidiBuffer::const_iterator mit = src->begin (); mit != src->end (); ++mit) {
2059                                                 rm->send_event (mit->timestamp (), mit->data (), mit->size ());
2060                                         }
2061                                 }
2062
2063                                 /* write back audio */
2064                                 i = 0;
2065                                 _pcmi->play_init (_samples_per_period);
2066                                 for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it, ++i) {
2067                                         _pcmi->play_chan (i, (const float*)(*it)->get_buffer (_samples_per_period), _samples_per_period);
2068                                 }
2069                                 for (; i < _pcmi->nplay (); ++i) {
2070                                         _pcmi->clear_chan (i, _samples_per_period);
2071                                 }
2072                                 _pcmi->play_done (_samples_per_period);
2073
2074                                 for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) {
2075                                         if (!(*s)->active) {
2076                                                 continue;
2077                                         }
2078                                         i = 0;
2079                                         for (std::vector<AlsaPort*>::const_iterator it = (*s)->outputs.begin (); it != (*s)->outputs.end (); ++it, ++i) {
2080                                                 (*s)->play_chan (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period);
2081                                         }
2082                                         (*s)->cycle_end ();
2083                                 }
2084
2085                                 nr -= _samples_per_period;
2086                                 _processed_samples += _samples_per_period;
2087
2088                                 _dsp_load_calc.set_max_time(_samplerate, _samples_per_period);
2089                                 _dsp_load_calc.set_start_timestamp_us (clock1);
2090                                 _dsp_load_calc.set_stop_timestamp_us (g_get_monotonic_time());
2091                                 _dsp_load = _dsp_load_calc.get_dsp_load ();
2092                                 ++last_n_periods;
2093                         }
2094
2095                         if (xrun && (_pcmi->capt_xrun() > 0 || _pcmi->play_xrun() > 0)) {
2096                                 engine.Xrun ();
2097                                 reset_dll = true;
2098 #if 0
2099                                 fprintf(stderr, "ALSA x-run read: %.2f ms, write: %.2f ms\n",
2100                                                 _pcmi->capt_xrun() * 1000.0, _pcmi->play_xrun() * 1000.0);
2101 #endif
2102                         }
2103                 } else {
2104                         // Freewheelin'
2105
2106                         // zero audio input buffers
2107                         for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
2108                                 memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
2109                         }
2110
2111                         clock1 = g_get_monotonic_time();
2112                         uint32_t i = 0;
2113                         for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
2114                                 static_cast<AlsaMidiBuffer*>((*it)->get_buffer(0))->clear ();
2115                                 AlsaMidiIn *rm = _rmidi_in.at(i);
2116                                 void *bptr = (*it)->get_buffer(0);
2117                                 midi_clear(bptr); // zero midi buffer
2118
2119                                 // TODO add an API call for this.
2120                                 pframes_t time;
2121                                 uint8_t data[64]; // match MaxAlsaEventSize in alsa_rawmidi.cc
2122                                 size_t size = sizeof(data);
2123                                 while (rm->recv_event (time, data, size)) {
2124                                         ; // discard midi-data from HW.
2125                                 }
2126                                 rm->sync_time (clock1);
2127                         }
2128
2129                         _last_process_start = 0;
2130                         if (engine.process_callback (_samples_per_period)) {
2131                                 _pcmi->pcm_stop ();
2132                                 _active = false;
2133                                 return 0;
2134                         }
2135
2136                         // drop all outgoing MIDI messages
2137                         for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) {
2138                                         void *bptr = (*it)->get_buffer(0);
2139                                         midi_clear(bptr);
2140                         }
2141
2142                         _dsp_load = 1.0;
2143                         reset_dll = true;
2144                         Glib::usleep (100); // don't hog cpu
2145                 }
2146
2147                 bool connections_changed = false;
2148                 bool ports_changed = false;
2149                 if (!pthread_mutex_trylock (&_port_callback_mutex)) {
2150                         if (_port_change_flag) {
2151                                 ports_changed = true;
2152                                 _port_change_flag = false;
2153                         }
2154                         if (!_port_connection_queue.empty ()) {
2155                                 connections_changed = true;
2156                         }
2157                         while (!_port_connection_queue.empty ()) {
2158                                 PortConnectData *c = _port_connection_queue.back ();
2159                                 manager.connect_callback (c->a, c->b, c->c);
2160                                 _port_connection_queue.pop_back ();
2161                                 delete c;
2162                         }
2163                         pthread_mutex_unlock (&_port_callback_mutex);
2164                 }
2165                 if (ports_changed) {
2166                         manager.registration_callback();
2167                 }
2168                 if (connections_changed) {
2169                         manager.graph_order_callback();
2170                 }
2171                 if (connections_changed || ports_changed) {
2172                         update_system_port_latecies (); // flush, clear
2173                         engine.latency_callback(false);
2174                         engine.latency_callback(true);
2175                 }
2176
2177         }
2178         _pcmi->pcm_stop ();
2179         _active = false;
2180         if (_run) {
2181                 engine.halted_callback("ALSA I/O error.");
2182         }
2183         return 0;
2184 }
2185
2186 /******************************************************************************/
2187
2188 bool
2189 AlsaAudioBackend::add_slave (const char*  device,
2190                              unsigned int slave_rate,
2191                              unsigned int slave_spp,
2192                              unsigned int duplex)
2193 {
2194         AudioSlave* s = new AudioSlave (device, duplex,
2195                         _samplerate, _samples_per_period,
2196                         slave_rate, slave_spp, 2);
2197
2198         if (s->state ()) {
2199                 // TODO parse error status
2200                 PBD::error << string_compose (_("Failed to create slave device '%1' error %2\n"), device, s->state ()) << endmsg;
2201                 goto errout;
2202         }
2203
2204         for (uint32_t i = 0, n = 1; i < s->ncapt (); ++i) {
2205                 char tmp[64];
2206                 do {
2207                         snprintf(tmp, sizeof(tmp), "extern:capture_%d", n);
2208                         if (find_port (tmp)) {
2209                                 ++n;
2210                         } else {
2211                                 break;
2212                         }
2213                 } while (1);
2214                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
2215                 if (!p) goto errout;
2216                 AlsaPort *ap = static_cast<AlsaPort*>(p);
2217                 s->inputs.push_back (ap);
2218         }
2219
2220         for (uint32_t i = 0, n = 1; i < s->nplay (); ++i) {
2221                 char tmp[64];
2222                 do {
2223                         snprintf(tmp, sizeof(tmp), "extern:playback_%d", n);
2224                         if (find_port (tmp)) {
2225                                 ++n;
2226                         } else {
2227                                 break;
2228                         }
2229                 } while (1);
2230                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
2231                 if (!p) goto errout;
2232                 AlsaPort *ap = static_cast<AlsaPort*>(p);
2233                 s->outputs.push_back (ap);
2234         }
2235
2236         if (!s->start ()) {
2237                 PBD::error << string_compose (_("Failed to start slave device '%1'\n"), device) << endmsg;
2238                 goto errout;
2239         }
2240         s->UpdateLatency.connect_same_thread (s->latency_connection, boost::bind (&AlsaAudioBackend::update_latencies, this));
2241         _slaves.push_back (s);
2242         return true;
2243
2244 errout:
2245         delete s; // releases device
2246         return false;
2247 }
2248
2249 AlsaAudioBackend::AudioSlave::AudioSlave (
2250                 const char*  device,
2251                 unsigned int duplex,
2252                 unsigned int master_rate,
2253                 unsigned int master_samples_per_period,
2254                 unsigned int slave_rate,
2255                 unsigned int slave_samples_per_period,
2256                 unsigned int periods_per_cycle)
2257         : AlsaDeviceReservation (device)
2258         , AlsaAudioSlave (
2259                         (duplex & 1) ? device : NULL /* playback */,
2260                         (duplex & 2) ? device : NULL /* capture */,
2261                         master_rate, master_samples_per_period,
2262                         slave_rate, slave_samples_per_period, periods_per_cycle)
2263         , active (false)
2264         , halt (false)
2265         , dead (false)
2266 {
2267         Halted.connect_same_thread (_halted_connection, boost::bind (&AudioSlave::halted, this));
2268 }
2269
2270 AlsaAudioBackend::AudioSlave::~AudioSlave ()
2271 {
2272         stop ();
2273 }
2274
2275 void
2276 AlsaAudioBackend::AudioSlave::halted ()
2277 {
2278         // Note: Halted() is emitted from the Slave's process thread.
2279         release_device ();
2280         halt = true;
2281 }
2282
2283 void
2284 AlsaAudioBackend::AudioSlave::update_latencies (uint32_t play, uint32_t capt)
2285 {
2286          LatencyRange lr;
2287          lr.min = lr.max = (capt);
2288          for (std::vector<AlsaPort*>::const_iterator it = inputs.begin (); it != inputs.end (); ++it) {
2289                 (*it)->set_latency_range (lr, false);
2290          }
2291
2292         lr.min = lr.max = play;
2293         for (std::vector<AlsaPort*>::const_iterator it = outputs.begin (); it != outputs.end (); ++it) {
2294                 (*it)->set_latency_range (lr, true);
2295         }
2296         printf (" ----- SLAVE LATENCY play=%d capt=%d\n", play, capt); // XXX DEBUG
2297         UpdateLatency (); /* EMIT SIGNAL */
2298 }
2299
2300 /******************************************************************************/
2301
2302 static boost::shared_ptr<AlsaAudioBackend> _instance;
2303
2304 static boost::shared_ptr<AudioBackend> backend_factory (AudioEngine& e);
2305 static int instantiate (const std::string& arg1, const std::string& /* arg2 */);
2306 static int deinstantiate ();
2307 static bool already_configured ();
2308 static bool available ();
2309
2310 static ARDOUR::AudioBackendInfo _descriptor = {
2311         "ALSA",
2312         instantiate,
2313         deinstantiate,
2314         backend_factory,
2315         already_configured,
2316         available
2317 };
2318
2319 static boost::shared_ptr<AudioBackend>
2320 backend_factory (AudioEngine& e)
2321 {
2322         if (!_instance) {
2323                 _instance.reset (new AlsaAudioBackend (e, _descriptor));
2324         }
2325         return _instance;
2326 }
2327
2328 static int
2329 instantiate (const std::string& arg1, const std::string& /* arg2 */)
2330 {
2331         s_instance_name = arg1;
2332         return 0;
2333 }
2334
2335 static int
2336 deinstantiate ()
2337 {
2338         _instance.reset ();
2339         return 0;
2340 }
2341
2342 static bool
2343 already_configured ()
2344 {
2345         return false;
2346 }
2347
2348 static bool
2349 available ()
2350 {
2351         return true;
2352 }
2353
2354 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
2355 {
2356         return &_descriptor;
2357 }
2358
2359
2360 /******************************************************************************/
2361 AlsaPort::AlsaPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
2362         : _alsa_backend (b)
2363         , _name  (name)
2364         , _flags (flags)
2365 {
2366         _capture_latency_range.min = 0;
2367         _capture_latency_range.max = 0;
2368         _playback_latency_range.min = 0;
2369         _playback_latency_range.max = 0;
2370 }
2371
2372 AlsaPort::~AlsaPort () {
2373         disconnect_all ();
2374 }
2375
2376 int AlsaPort::connect (AlsaPort *port)
2377 {
2378         if (!port) {
2379                 PBD::error << _("AlsaPort::connect (): invalid (null) port") << endmsg;
2380                 return -1;
2381         }
2382
2383         if (type () != port->type ()) {
2384                 PBD::error << _("AlsaPort::connect (): wrong port-type") << endmsg;
2385                 return -1;
2386         }
2387
2388         if (is_output () && port->is_output ()) {
2389                 PBD::error << _("AlsaPort::connect (): cannot inter-connect output ports.") << endmsg;
2390                 return -1;
2391         }
2392
2393         if (is_input () && port->is_input ()) {
2394                 PBD::error << _("AlsaPort::connect (): cannot inter-connect input ports.") << endmsg;
2395                 return -1;
2396         }
2397
2398         if (this == port) {
2399                 PBD::error << _("AlsaPort::connect (): cannot self-connect ports.") << endmsg;
2400                 return -1;
2401         }
2402
2403         if (is_connected (port)) {
2404 #if 0 // don't bother to warn about this for now. just ignore it
2405                 PBD::error << _("AlsaPort::connect (): ports are already connected:")
2406                         << " (" << name () << ") -> (" << port->name () << ")"
2407                         << endmsg;
2408 #endif
2409                 return -1;
2410         }
2411
2412         _connect (port, true);
2413         return 0;
2414 }
2415
2416 void AlsaPort::_connect (AlsaPort *port, bool callback)
2417 {
2418         _connections.insert (port);
2419         if (callback) {
2420                 port->_connect (this, false);
2421                 _alsa_backend.port_connect_callback (name(),  port->name(), true);
2422         }
2423 }
2424
2425 int AlsaPort::disconnect (AlsaPort *port)
2426 {
2427         if (!port) {
2428                 PBD::error << _("AlsaPort::disconnect (): invalid (null) port") << endmsg;
2429                 return -1;
2430         }
2431
2432         if (!is_connected (port)) {
2433                 PBD::error << _("AlsaPort::disconnect (): ports are not connected:")
2434                         << " (" << name () << ") -> (" << port->name () << ")"
2435                         << endmsg;
2436                 return -1;
2437         }
2438         _disconnect (port, true);
2439         return 0;
2440 }
2441
2442 void AlsaPort::_disconnect (AlsaPort *port, bool callback)
2443 {
2444         std::set<AlsaPort*>::iterator it = _connections.find (port);
2445         assert (it != _connections.end ());
2446         _connections.erase (it);
2447         if (callback) {
2448                 port->_disconnect (this, false);
2449                 _alsa_backend.port_connect_callback (name(),  port->name(), false);
2450         }
2451 }
2452
2453
2454 void AlsaPort::disconnect_all ()
2455 {
2456         while (!_connections.empty ()) {
2457                 std::set<AlsaPort*>::iterator it = _connections.begin ();
2458                 (*it)->_disconnect (this, false);
2459                 _alsa_backend.port_connect_callback (name(), (*it)->name(), false);
2460                 _connections.erase (it);
2461         }
2462 }
2463
2464 bool
2465 AlsaPort::is_connected (const AlsaPort *port) const
2466 {
2467         return _connections.find (const_cast<AlsaPort *>(port)) != _connections.end ();
2468 }
2469
2470 bool AlsaPort::is_physically_connected () const
2471 {
2472         for (std::set<AlsaPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
2473                 if ((*it)->is_physical ()) {
2474                         return true;
2475                 }
2476         }
2477         return false;
2478 }
2479
2480 void
2481 AlsaPort::set_latency_range (const LatencyRange &latency_range, bool for_playback)
2482 {
2483         if (for_playback) {
2484                 _playback_latency_range = latency_range;
2485         } else {
2486                 _capture_latency_range = latency_range;
2487         }
2488
2489         for (std::set<AlsaPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
2490                 if ((*it)->is_physical ()) {
2491                         (*it)->update_connected_latency (is_input ());
2492                 }
2493         }
2494 }
2495
2496 void
2497 AlsaPort::update_connected_latency (bool for_playback)
2498 {
2499         LatencyRange lr;
2500         lr.min = lr.max = 0;
2501         for (std::set<AlsaPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
2502                 LatencyRange l;
2503                 l = (*it)->latency_range (for_playback);
2504                 lr.min = std::max (lr.min, l.min);
2505                 lr.max = std::max (lr.max, l.max);
2506         }
2507         set_latency_range (lr, for_playback);
2508 }
2509
2510 /******************************************************************************/
2511
2512 AlsaAudioPort::AlsaAudioPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
2513         : AlsaPort (b, name, flags)
2514 {
2515         memset (_buffer, 0, sizeof (_buffer));
2516         mlock(_buffer, sizeof (_buffer));
2517 }
2518
2519 AlsaAudioPort::~AlsaAudioPort () { }
2520
2521 void* AlsaAudioPort::get_buffer (pframes_t n_samples)
2522 {
2523         if (is_input ()) {
2524                 const std::set<AlsaPort *>& connections = get_connections ();
2525                 std::set<AlsaPort*>::const_iterator it = connections.begin ();
2526                 if (it == connections.end ()) {
2527                         memset (_buffer, 0, n_samples * sizeof (Sample));
2528                 } else {
2529                         AlsaAudioPort const * source = static_cast<const AlsaAudioPort*>(*it);
2530                         assert (source && source->is_output ());
2531                         memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
2532                         while (++it != connections.end ()) {
2533                                 source = static_cast<const AlsaAudioPort*>(*it);
2534                                 assert (source && source->is_output ());
2535                                 Sample* dst = buffer ();
2536                                 const Sample* src = source->const_buffer ();
2537                                 for (uint32_t s = 0; s < n_samples; ++s, ++dst, ++src) {
2538                                         *dst += *src;
2539                                 }
2540                         }
2541                 }
2542         }
2543         return _buffer;
2544 }
2545
2546
2547 AlsaMidiPort::AlsaMidiPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
2548         : AlsaPort (b, name, flags)
2549         , _n_periods (1)
2550         , _bufperiod (0)
2551 {
2552         _buffer[0].clear ();
2553         _buffer[1].clear ();
2554         _buffer[2].clear ();
2555
2556         _buffer[0].reserve(256);
2557         _buffer[1].reserve(256);
2558         _buffer[2].reserve(256);
2559 }
2560
2561 AlsaMidiPort::~AlsaMidiPort () { }
2562
2563 struct MidiEventSorter {
2564         bool operator() (AlsaMidiEvent const& a, AlsaMidiEvent const& b) {
2565                 return a < b;
2566         }
2567 };
2568
2569 void* AlsaMidiPort::get_buffer (pframes_t /* nframes */)
2570 {
2571         if (is_input ()) {
2572                 (_buffer[_bufperiod]).clear ();
2573                 const std::set<AlsaPort*>& connections = get_connections ();
2574                 for (std::set<AlsaPort*>::const_iterator i = connections.begin ();
2575                                 i != connections.end ();
2576                                 ++i) {
2577                         const AlsaMidiBuffer * src = static_cast<const AlsaMidiPort*>(*i)->const_buffer ();
2578                         for (AlsaMidiBuffer::const_iterator it = src->begin (); it != src->end (); ++it) {
2579                                 (_buffer[_bufperiod]).push_back (*it);
2580                         }
2581                 }
2582                 std::stable_sort ((_buffer[_bufperiod]).begin (), (_buffer[_bufperiod]).end (), MidiEventSorter());
2583         }
2584         return &(_buffer[_bufperiod]);
2585 }
2586
2587 AlsaMidiEvent::AlsaMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size)
2588         : _size (size)
2589         , _timestamp (timestamp)
2590 {
2591         if (size > 0 && size < MaxAlsaMidiEventSize) {
2592                 memcpy (_data, data, size);
2593         }
2594 }
2595
2596 AlsaMidiEvent::AlsaMidiEvent (const AlsaMidiEvent& other)
2597         : _size (other.size ())
2598         , _timestamp (other.timestamp ())
2599 {
2600         if (other._size > 0) {
2601                 assert (other._size < MaxAlsaMidiEventSize);
2602                 memcpy (_data, other._data, other._size);
2603         }
2604 };
2605
2606 /******************************************************************************/
2607
2608 AlsaDeviceReservation::AlsaDeviceReservation ()
2609         : _device_reservation (0)
2610 {}
2611
2612 AlsaDeviceReservation::AlsaDeviceReservation (const char* device_name)
2613         : _device_reservation (0)
2614 {
2615         acquire_device (device_name);
2616 }
2617
2618 AlsaDeviceReservation::~AlsaDeviceReservation ()
2619 {
2620         release_device ();
2621 }
2622
2623 bool
2624 AlsaDeviceReservation::acquire_device (const char* device_name)
2625 {
2626         int device_number = card_to_num(device_name);
2627         if (device_number < 0) return false;
2628
2629         assert(_device_reservation == 0);
2630         _reservation_succeeded = false;
2631
2632         std::string request_device_exe;
2633         if (!PBD::find_file (
2634                                 PBD::Searchpath(Glib::build_filename(ARDOUR::ardour_dll_directory(), "ardouralsautil")
2635                                         + G_SEARCHPATH_SEPARATOR_S + ARDOUR::ardour_dll_directory()),
2636                                 "ardour-request-device", request_device_exe))
2637         {
2638                 PBD::warning << "ardour-request-device binary was not found..'" << endmsg;
2639                 return false;
2640         }
2641
2642         char **argp;
2643         char tmp[128];
2644         argp=(char**) calloc(5,sizeof(char*));
2645         argp[0] = strdup(request_device_exe.c_str());
2646         argp[1] = strdup("-P");
2647         snprintf(tmp, sizeof(tmp), "%d", getpid());
2648         argp[2] = strdup(tmp);
2649         snprintf(tmp, sizeof(tmp), "Audio%d", device_number);
2650         argp[3] = strdup(tmp);
2651         argp[4] = 0;
2652
2653         _device_reservation = new ARDOUR::SystemExec(request_device_exe, argp);
2654         _device_reservation->ReadStdout.connect_same_thread (_reservation_connection, boost::bind (&AlsaDeviceReservation::reservation_stdout, this, _1 ,_2));
2655         _device_reservation->Terminated.connect_same_thread (_reservation_connection, boost::bind (&AlsaDeviceReservation::release_device, this));
2656
2657         if (_device_reservation->start(0)) {
2658                 PBD::warning << _("AlsaAudioBackend: Device Request failed.") << endmsg;
2659                 release_device();
2660                 return false;
2661         }
2662
2663         /* wait to check if reservation suceeded. */
2664         int timeout = 500; // 5 sec
2665         while (_device_reservation && !_reservation_succeeded && --timeout > 0) {
2666                 Glib::usleep(10000);
2667         }
2668
2669         if (timeout == 0 || !_reservation_succeeded) {
2670                 PBD::warning << _("AlsaAudioBackend: Device Reservation failed.") << endmsg;
2671                 release_device();
2672                 return false;
2673         }
2674         return true;
2675 }
2676
2677 void
2678 AlsaDeviceReservation::release_device ()
2679 {
2680         _reservation_connection.drop_connections();
2681         ARDOUR::SystemExec* tmp = _device_reservation;
2682         _device_reservation = 0;
2683         delete tmp;
2684 }
2685
2686 void
2687 AlsaDeviceReservation::reservation_stdout (std::string d, size_t /* s */)
2688 {
2689   if (d.substr(0, 19) == "Acquired audio-card") {
2690                 _reservation_succeeded = true;
2691         }
2692 }