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