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