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