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