add 'available' interface to the AudioBackendInfo
[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 #include "rt_thread.h"
28
29 #include "pbd/compose.h"
30 #include "pbd/error.h"
31 #include "pbd/file_utils.h"
32 #include "ardour/filesystem_paths.h"
33 #include "ardour/port_manager.h"
34 #include "ardouralsautil/devicelist.h"
35 #include "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::_audio_device_status;
43 std::vector<AudioBackend::DeviceStatus> AlsaAudioBackend::_midi_device_status;
44
45 AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info)
46         : AudioBackend (e, info)
47         , _pcmi (0)
48         , _run (false)
49         , _active (false)
50         , _freewheeling (false)
51         , _measure_latency (false)
52         , _audio_device("")
53         , _midi_driver_option(_("None"))
54         , _device_reservation(0)
55         , _samplerate (48000)
56         , _samples_per_period (1024)
57         , _periods_per_cycle (2)
58         , _n_inputs (0)
59         , _n_outputs (0)
60         , _systemic_audio_input_latency (0)
61         , _systemic_audio_output_latency (0)
62         , _dsp_load (0)
63         , _processed_samples (0)
64         , _port_change_flag (false)
65 {
66         _instance_name = s_instance_name;
67         pthread_mutex_init (&_port_callback_mutex, 0);
68 }
69
70 AlsaAudioBackend::~AlsaAudioBackend ()
71 {
72         pthread_mutex_destroy (&_port_callback_mutex);
73 }
74
75 /* AUDIOBACKEND API */
76
77 std::string
78 AlsaAudioBackend::name () const
79 {
80         return X_("ALSA");
81 }
82
83 bool
84 AlsaAudioBackend::is_realtime () const
85 {
86         return true;
87 }
88
89 std::vector<AudioBackend::DeviceStatus>
90 AlsaAudioBackend::enumerate_devices () const
91 {
92         _audio_device_status.clear();
93         std::map<std::string, std::string> devices;
94         get_alsa_audio_device_names(devices);
95         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
96                 if (_audio_device == "") _audio_device = i->first;
97                 _audio_device_status.push_back (DeviceStatus (i->first, true));
98         }
99         return _audio_device_status;
100 }
101
102 void
103 AlsaAudioBackend::reservation_stdout (std::string d, size_t /* s */)
104 {
105   if (d.substr(0, 19) == "Acquired audio-card") {
106                 _reservation_succeeded = true;
107         }
108 }
109
110 void
111 AlsaAudioBackend::release_device()
112 {
113         _reservation_connection.drop_connections();
114         ARDOUR::SystemExec * tmp = _device_reservation;
115         _device_reservation = 0;
116         delete tmp;
117 }
118
119 bool
120 AlsaAudioBackend::acquire_device(const char* device_name)
121 {
122         /* This is  quick hack, ideally we'll link against libdbus and implement a dbus-listener
123          * that owns the device. here we try to get away by just requesting it and then block it...
124          * (pulseaudio periodically checks anyway)
125          *
126          * dbus-send --session --print-reply --type=method_call --dest=org.freedesktop.ReserveDevice1.Audio2 /org/freedesktop/ReserveDevice1/Audio2 org.freedesktop.ReserveDevice1.RequestRelease int32:4
127          * -> should not return  'boolean false'
128          */
129         int device_number = card_to_num(device_name);
130         if (device_number < 0) return false;
131
132         assert(_device_reservation == 0);
133         _reservation_succeeded = false;
134
135         std::string request_device_exe;
136         if (!PBD::find_file (
137                                 PBD::Searchpath(Glib::build_filename(ARDOUR::ardour_dll_directory(), "ardouralsautil")
138                                         + G_SEARCHPATH_SEPARATOR_S + ARDOUR::ardour_dll_directory()),
139                                 "ardour-request-device", request_device_exe))
140         {
141                 PBD::warning << "ardour-request-device binary was not found..'" << endmsg;
142                 return false;
143         }
144         else
145         {
146                 char **argp;
147                 char tmp[128];
148                 argp=(char**) calloc(5,sizeof(char*));
149                 argp[0] = strdup(request_device_exe.c_str());
150                 argp[1] = strdup("-P");
151                 snprintf(tmp, sizeof(tmp), "%d", getpid());
152                 argp[2] = strdup(tmp);
153                 snprintf(tmp, sizeof(tmp), "Audio%d", device_number);
154                 argp[3] = strdup(tmp);
155                 argp[4] = 0;
156
157                 _device_reservation = new ARDOUR::SystemExec(request_device_exe, argp);
158                 _device_reservation->ReadStdout.connect_same_thread (_reservation_connection, boost::bind (&AlsaAudioBackend::reservation_stdout, this, _1 ,_2));
159                 _device_reservation->Terminated.connect_same_thread (_reservation_connection, boost::bind (&AlsaAudioBackend::release_device, this));
160                 if (_device_reservation->start(0)) {
161                         PBD::warning << _("AlsaAudioBackend: Device Request failed.") << endmsg;
162                         release_device();
163                         return false;
164                 }
165         }
166         // wait to check if reservation suceeded.
167         int timeout = 500; // 5 sec
168         while (_device_reservation && !_reservation_succeeded && --timeout > 0) {
169                 Glib::usleep(10000);
170         }
171         if (timeout == 0 || !_reservation_succeeded) {
172                 PBD::warning << _("AlsaAudioBackend: Device Reservation failed.") << endmsg;
173                 release_device();
174                 return false;
175         }
176         return true;
177 }
178
179 std::vector<float>
180 AlsaAudioBackend::available_sample_rates (const std::string&) const
181 {
182         std::vector<float> sr;
183         sr.push_back (8000.0);
184         sr.push_back (22050.0);
185         sr.push_back (24000.0);
186         sr.push_back (44100.0);
187         sr.push_back (48000.0);
188         sr.push_back (88200.0);
189         sr.push_back (96000.0);
190         sr.push_back (176400.0);
191         sr.push_back (192000.0);
192         return sr;
193 }
194
195 std::vector<uint32_t>
196 AlsaAudioBackend::available_buffer_sizes (const std::string&) const
197 {
198         std::vector<uint32_t> bs;
199         bs.push_back (32);
200         bs.push_back (64);
201         bs.push_back (128);
202         bs.push_back (256);
203         bs.push_back (512);
204         bs.push_back (1024);
205         bs.push_back (2048);
206         bs.push_back (4096);
207         bs.push_back (8192);
208         return bs;
209 }
210
211 uint32_t
212 AlsaAudioBackend::available_input_channel_count (const std::string&) const
213 {
214         return 128; // TODO query current device
215 }
216
217 uint32_t
218 AlsaAudioBackend::available_output_channel_count (const std::string&) const
219 {
220         return 128; // TODO query current device
221 }
222
223 bool
224 AlsaAudioBackend::can_change_sample_rate_when_running () const
225 {
226         return false;
227 }
228
229 bool
230 AlsaAudioBackend::can_change_buffer_size_when_running () const
231 {
232         return false;
233 }
234
235 int
236 AlsaAudioBackend::set_device_name (const std::string& d)
237 {
238         _audio_device = d;
239         return 0;
240 }
241
242 int
243 AlsaAudioBackend::set_sample_rate (float sr)
244 {
245         if (sr <= 0) { return -1; }
246         _samplerate = sr;
247         engine.sample_rate_change (sr);
248         return 0;
249 }
250
251 int
252 AlsaAudioBackend::set_buffer_size (uint32_t bs)
253 {
254         if (bs <= 0 || bs >= _max_buffer_size) {
255                 return -1;
256         }
257         _samples_per_period = bs;
258         engine.buffer_size_change (bs);
259         return 0;
260 }
261
262 int
263 AlsaAudioBackend::set_interleaved (bool yn)
264 {
265         if (!yn) { return 0; }
266         return -1;
267 }
268
269 int
270 AlsaAudioBackend::set_input_channels (uint32_t cc)
271 {
272         _n_inputs = cc;
273         return 0;
274 }
275
276 int
277 AlsaAudioBackend::set_output_channels (uint32_t cc)
278 {
279         _n_outputs = cc;
280         return 0;
281 }
282
283 int
284 AlsaAudioBackend::set_systemic_input_latency (uint32_t sl)
285 {
286         _systemic_audio_input_latency = sl;
287         return 0;
288 }
289
290 int
291 AlsaAudioBackend::set_systemic_output_latency (uint32_t sl)
292 {
293         _systemic_audio_output_latency = sl;
294         return 0;
295 }
296
297 int
298 AlsaAudioBackend::set_systemic_midi_input_latency (std::string const device, uint32_t sl)
299 {
300         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
301         if (!nfo) return -1;
302         nfo->systemic_input_latency = sl;
303         return 0;
304 }
305
306 int
307 AlsaAudioBackend::set_systemic_midi_output_latency (std::string const device, uint32_t sl)
308 {
309         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
310         if (!nfo) return -1;
311         nfo->systemic_output_latency = sl;
312         return 0;
313 }
314
315 /* Retrieving parameters */
316 std::string
317 AlsaAudioBackend::device_name () const
318 {
319         return _audio_device;
320 }
321
322 float
323 AlsaAudioBackend::sample_rate () const
324 {
325         return _samplerate;
326 }
327
328 uint32_t
329 AlsaAudioBackend::buffer_size () const
330 {
331         return _samples_per_period;
332 }
333
334 bool
335 AlsaAudioBackend::interleaved () const
336 {
337         return false;
338 }
339
340 uint32_t
341 AlsaAudioBackend::input_channels () const
342 {
343         return _n_inputs;
344 }
345
346 uint32_t
347 AlsaAudioBackend::output_channels () const
348 {
349         return _n_outputs;
350 }
351
352 uint32_t
353 AlsaAudioBackend::systemic_input_latency () const
354 {
355         return _systemic_audio_input_latency;
356 }
357
358 uint32_t
359 AlsaAudioBackend::systemic_output_latency () const
360 {
361         return _systemic_audio_output_latency;
362 }
363
364 uint32_t
365 AlsaAudioBackend::systemic_midi_input_latency (std::string const device) const
366 {
367         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
368         if (!nfo) return 0;
369         return nfo->systemic_input_latency;
370 }
371
372 uint32_t
373 AlsaAudioBackend::systemic_midi_output_latency (std::string const device) const
374 {
375         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
376         if (!nfo) return 0;
377         return nfo->systemic_output_latency;
378 }
379
380 /* MIDI */
381 struct AlsaAudioBackend::AlsaMidiDeviceInfo *
382 AlsaAudioBackend::midi_device_info(std::string const name) const {
383         for (std::map<std::string, struct AlsaMidiDeviceInfo*>::const_iterator i = _midi_devices.begin (); i != _midi_devices.end(); ++i) {
384                 if (i->first == name) {
385                         return (i->second);
386                 }
387         }
388
389         assert(_midi_driver_option != _("None"));
390
391         std::map<std::string, std::string> devices;
392         if (_midi_driver_option == _("ALSA raw devices")) {
393                 get_alsa_rawmidi_device_names(devices);
394         } else {
395                 get_alsa_sequencer_names (devices);
396         }
397
398         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
399                 if (i->first == name) {
400                         _midi_devices[name] = new AlsaMidiDeviceInfo();
401                         return _midi_devices[name];
402                 }
403         }
404         return 0;
405 }
406
407 std::vector<std::string>
408 AlsaAudioBackend::enumerate_midi_options () const
409 {
410         if (_midi_options.empty()) {
411                 _midi_options.push_back (_("None"));
412                 _midi_options.push_back (_("ALSA raw devices"));
413                 _midi_options.push_back (_("ALSA sequencer"));
414         }
415         return _midi_options;
416 }
417
418 std::vector<AudioBackend::DeviceStatus>
419 AlsaAudioBackend::enumerate_midi_devices () const
420 {
421         _midi_device_status.clear();
422         std::map<std::string, std::string> devices;
423
424         if (_midi_driver_option == _("ALSA raw devices")) {
425                 get_alsa_rawmidi_device_names (devices);
426         }
427         else if (_midi_driver_option == _("ALSA sequencer")) {
428                 get_alsa_sequencer_names (devices);
429         }
430
431         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
432                 _midi_device_status.push_back (DeviceStatus (i->first, true));
433         }
434         return _midi_device_status;
435 }
436
437 int
438 AlsaAudioBackend::set_midi_option (const std::string& opt)
439 {
440         if (opt != _("None") && opt != _("ALSA raw devices") && opt != _("ALSA sequencer")) {
441                 return -1;
442         }
443         _midi_driver_option = opt;
444         return 0;
445 }
446
447 std::string
448 AlsaAudioBackend::midi_option () const
449 {
450         return _midi_driver_option;
451 }
452
453 int
454 AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable)
455 {
456         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
457         if (!nfo) return -1;
458         nfo->enabled = enable;
459         return 0;
460 }
461
462 bool
463 AlsaAudioBackend::midi_device_enabled (std::string const device) const
464 {
465         struct AlsaMidiDeviceInfo * nfo = midi_device_info(device);
466         if (!nfo) return false;
467         return nfo->enabled;
468 }
469
470 /* State Control */
471
472 static void * pthread_process (void *arg)
473 {
474         AlsaAudioBackend *d = static_cast<AlsaAudioBackend *>(arg);
475         d->main_process_thread ();
476         pthread_exit (0);
477         return 0;
478 }
479
480 int
481 AlsaAudioBackend::_start (bool for_latency_measurement)
482 {
483         if (!_active && _run) {
484                 // recover from 'halted', reap threads
485                 stop();
486         }
487
488         if (_active || _run) {
489                 PBD::error << _("AlsaAudioBackend: already active.") << endmsg;
490                 return -1;
491         }
492
493         if (_ports.size()) {
494                 PBD::warning << _("AlsaAudioBackend: recovering from unclean shutdown, port registry is not empty.") << endmsg;
495                 _system_inputs.clear();
496                 _system_outputs.clear();
497                 _system_midi_in.clear();
498                 _system_midi_out.clear();
499                 _ports.clear();
500         }
501
502         release_device();
503
504         assert(_rmidi_in.size() == 0);
505         assert(_rmidi_out.size() == 0);
506         assert(_pcmi == 0);
507
508         std::string alsa_device;
509         std::map<std::string, std::string> devices;
510         get_alsa_audio_device_names(devices);
511         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
512                 if (i->first == _audio_device) {
513                         alsa_device = i->second;
514                         break;
515                 }
516         }
517
518         acquire_device(alsa_device.c_str());
519         _pcmi = new Alsa_pcmi (alsa_device.c_str(), alsa_device.c_str(), 0, _samplerate, _samples_per_period, _periods_per_cycle, 0);
520         switch (_pcmi->state ()) {
521                 case 0: /* OK */ break;
522                 case -1: PBD::error << _("AlsaAudioBackend: failed to open device.") << endmsg; break;
523                 case -2: PBD::error << _("AlsaAudioBackend: failed to allocate parameters.") << endmsg; break;
524                 case -3: PBD::error << _("AlsaAudioBackend: cannot set requested sample rate.") << endmsg; break;
525                 case -4: PBD::error << _("AlsaAudioBackend: cannot set requested period size.") << endmsg; break;
526                 case -5: PBD::error << _("AlsaAudioBackend: cannot set requested number of periods.") << endmsg; break;
527                 case -6: PBD::error << _("AlsaAudioBackend: unsupported sample format.") << endmsg; break;
528                 default: PBD::error << _("AlsaAudioBackend: initialization failed.") << endmsg; break;
529         }
530         if (_pcmi->state ()) {
531                 delete _pcmi; _pcmi = 0;
532                 release_device();
533                 return -1;
534         }
535
536 #ifndef NDEBUG
537         _pcmi->printinfo ();
538 #endif
539
540         if (_n_outputs != _pcmi->nplay ()) {
541                 if (_n_outputs == 0) {
542                  _n_outputs = _pcmi->nplay ();
543                 } else {
544                  _n_outputs = std::min (_n_outputs, _pcmi->nplay ());
545                 }
546                 PBD::warning << _("AlsaAudioBackend: adjusted output channel count to match device.") << endmsg;
547         }
548
549         if (_n_inputs != _pcmi->ncapt ()) {
550                 if (_n_inputs == 0) {
551                  _n_inputs = _pcmi->ncapt ();
552                 } else {
553                  _n_inputs = std::min (_n_inputs, _pcmi->ncapt ());
554                 }
555                 PBD::warning << _("AlsaAudioBackend: adjusted input channel count to match device.") << endmsg;
556         }
557
558         if (_pcmi->fsize() != _samples_per_period) {
559                 _samples_per_period = _pcmi->fsize();
560                 PBD::warning << _("AlsaAudioBackend: samples per period does not match.") << endmsg;
561         }
562
563         if (_pcmi->fsamp() != _samplerate) {
564                 _samplerate = _pcmi->fsamp();
565                 engine.sample_rate_change (_samplerate);
566                 PBD::warning << _("AlsaAudioBackend: sample rate does not match.") << endmsg;
567         }
568
569         _measure_latency = for_latency_measurement;
570
571         register_system_midi_ports();
572
573         if (register_system_audio_ports()) {
574                 PBD::error << _("AlsaAudioBackend: failed to register system ports.") << endmsg;
575                 delete _pcmi; _pcmi = 0;
576                 release_device();
577                 return -1;
578         }
579
580         engine.sample_rate_change (_samplerate);
581         engine.buffer_size_change (_samples_per_period);
582
583         if (engine.reestablish_ports ()) {
584                 PBD::error << _("AlsaAudioBackend: Could not re-establish ports.") << endmsg;
585                 delete _pcmi; _pcmi = 0;
586                 release_device();
587                 return -1;
588         }
589
590         engine.reconnect_ports ();
591         _run = true;
592         _port_change_flag = false;
593
594         if (_realtime_pthread_create (SCHED_FIFO, -20, 100000,
595                                 &_main_thread, pthread_process, this))
596         {
597                 if (pthread_create (&_main_thread, NULL, pthread_process, this))
598                 {
599                         PBD::error << _("AlsaAudioBackend: failed to create process thread.") << endmsg;
600                         delete _pcmi; _pcmi = 0;
601                         release_device();
602                         _run = false;
603                         return -1;
604                 } else {
605                         PBD::warning << _("AlsaAudioBackend: cannot acquire realtime permissions.") << endmsg;
606                 }
607         }
608
609         int timeout = 5000;
610         while (!_active && --timeout > 0) { Glib::usleep (1000); }
611
612         if (timeout == 0 || !_active) {
613                 PBD::error << _("AlsaAudioBackend: failed to start process thread.") << endmsg;
614                 delete _pcmi; _pcmi = 0;
615                 release_device();
616                 _run = false;
617                 return -1;
618         }
619
620         return 0;
621 }
622
623 int
624 AlsaAudioBackend::stop ()
625 {
626         void *status;
627         if (!_run) {
628                 return 0;
629         }
630
631         _run = false;
632         if (pthread_join (_main_thread, &status)) {
633                 PBD::error << _("AlsaAudioBackend: failed to terminate.") << endmsg;
634                 return -1;
635         }
636
637         while (!_rmidi_out.empty ()) {
638                 AlsaMidiIO *m = _rmidi_out.back ();
639                 m->stop();
640                 _rmidi_out.pop_back ();
641                 delete m;
642         }
643         while (!_rmidi_in.empty ()) {
644                 AlsaMidiIO *m = _rmidi_in.back ();
645                 m->stop();
646                 _rmidi_in.pop_back ();
647                 delete m;
648         }
649
650         unregister_ports();
651         delete _pcmi; _pcmi = 0;
652         release_device();
653
654         return (_active == false) ? 0 : -1;
655 }
656
657 int
658 AlsaAudioBackend::freewheel (bool onoff)
659 {
660         if (onoff == _freewheeling) {
661                 return 0;
662         }
663         _freewheeling = onoff;
664         engine.freewheel_callback (onoff);
665         return 0;
666 }
667
668 float
669 AlsaAudioBackend::dsp_load () const
670 {
671         return 100.f * _dsp_load;
672 }
673
674 size_t
675 AlsaAudioBackend::raw_buffer_size (DataType t)
676 {
677         switch (t) {
678                 case DataType::AUDIO:
679                         return _samples_per_period * sizeof(Sample);
680                 case DataType::MIDI:
681                         return _max_buffer_size; // XXX not really limited
682         }
683         return 0;
684 }
685
686 /* Process time */
687 pframes_t
688 AlsaAudioBackend::sample_time ()
689 {
690         return _processed_samples;
691 }
692
693 pframes_t
694 AlsaAudioBackend::sample_time_at_cycle_start ()
695 {
696         return _processed_samples;
697 }
698
699 pframes_t
700 AlsaAudioBackend::samples_since_cycle_start ()
701 {
702         return 0;
703 }
704
705
706 void *
707 AlsaAudioBackend::alsa_process_thread (void *arg)
708 {
709         ThreadData* td = reinterpret_cast<ThreadData*> (arg);
710         boost::function<void ()> f = td->f;
711         delete td;
712         f ();
713         return 0;
714 }
715
716 int
717 AlsaAudioBackend::create_process_thread (boost::function<void()> func)
718 {
719         pthread_t thread_id;
720         pthread_attr_t attr;
721         size_t stacksize = 100000;
722
723         ThreadData* td = new ThreadData (this, func, stacksize);
724
725         if (_realtime_pthread_create (SCHED_FIFO, -21, stacksize,
726                                 &thread_id, alsa_process_thread, td)) {
727                 pthread_attr_init (&attr);
728                 pthread_attr_setstacksize (&attr, stacksize);
729                 if (pthread_create (&thread_id, &attr, alsa_process_thread, td)) {
730                         PBD::error << _("AudioEngine: cannot create process thread.") << endmsg;
731                         pthread_attr_destroy (&attr);
732                         return -1;
733                 }
734                 pthread_attr_destroy (&attr);
735         }
736
737         _threads.push_back (thread_id);
738         return 0;
739 }
740
741 int
742 AlsaAudioBackend::join_process_threads ()
743 {
744         int rv = 0;
745
746         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
747         {
748                 void *status;
749                 if (pthread_join (*i, &status)) {
750                         PBD::error << _("AudioEngine: cannot terminate process thread.") << endmsg;
751                         rv -= 1;
752                 }
753         }
754         _threads.clear ();
755         return rv;
756 }
757
758 bool
759 AlsaAudioBackend::in_process_thread ()
760 {
761         if (pthread_equal (_main_thread, pthread_self()) != 0) {
762                 return true;
763         }
764
765         for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
766         {
767                 if (pthread_equal (*i, pthread_self ()) != 0) {
768                         return true;
769                 }
770         }
771         return false;
772 }
773
774 uint32_t
775 AlsaAudioBackend::process_thread_count ()
776 {
777         return _threads.size ();
778 }
779
780 void
781 AlsaAudioBackend::update_latencies ()
782 {
783         // trigger latency callback in RT thread (locked graph)
784         port_connect_add_remove_callback();
785 }
786
787 /* PORTENGINE API */
788
789 void*
790 AlsaAudioBackend::private_handle () const
791 {
792         return NULL;
793 }
794
795 const std::string&
796 AlsaAudioBackend::my_name () const
797 {
798         return _instance_name;
799 }
800
801 bool
802 AlsaAudioBackend::available () const
803 {
804         return _run && _active;
805 }
806
807 uint32_t
808 AlsaAudioBackend::port_name_size () const
809 {
810         return 256;
811 }
812
813 int
814 AlsaAudioBackend::set_port_name (PortEngine::PortHandle port, const std::string& name)
815 {
816         if (!valid_port (port)) {
817                 PBD::error << _("AlsaBackend::set_port_name: Invalid Port(s)") << endmsg;
818                 return -1;
819         }
820         return static_cast<AlsaPort*>(port)->set_name (_instance_name + ":" + name);
821 }
822
823 std::string
824 AlsaAudioBackend::get_port_name (PortEngine::PortHandle port) const
825 {
826         if (!valid_port (port)) {
827                 PBD::error << _("AlsaBackend::get_port_name: Invalid Port(s)") << endmsg;
828                 return std::string ();
829         }
830         return static_cast<AlsaPort*>(port)->name ();
831 }
832
833 PortEngine::PortHandle
834 AlsaAudioBackend::get_port_by_name (const std::string& name) const
835 {
836         PortHandle port = (PortHandle) find_port (name);
837         return port;
838 }
839
840 int
841 AlsaAudioBackend::get_ports (
842                 const std::string& port_name_pattern,
843                 DataType type, PortFlags flags,
844                 std::vector<std::string>& port_names) const
845 {
846         int rv = 0;
847         regex_t port_regex;
848         bool use_regexp = false;
849         if (port_name_pattern.size () > 0) {
850                 if (!regcomp (&port_regex, port_name_pattern.c_str (), REG_EXTENDED|REG_NOSUB)) {
851                         use_regexp = true;
852                 }
853         }
854         for (size_t i = 0; i < _ports.size (); ++i) {
855                 AlsaPort* port = _ports[i];
856                 if ((port->type () == type) && (port->flags () & flags)) {
857                         if (!use_regexp || !regexec (&port_regex, port->name ().c_str (), 0, NULL, 0)) {
858                                 port_names.push_back (port->name ());
859                                 ++rv;
860                         }
861                 }
862         }
863         if (use_regexp) {
864                 regfree (&port_regex);
865         }
866         return rv;
867 }
868
869 DataType
870 AlsaAudioBackend::port_data_type (PortEngine::PortHandle port) const
871 {
872         if (!valid_port (port)) {
873                 return DataType::NIL;
874         }
875         return static_cast<AlsaPort*>(port)->type ();
876 }
877
878 PortEngine::PortHandle
879 AlsaAudioBackend::register_port (
880                 const std::string& name,
881                 ARDOUR::DataType type,
882                 ARDOUR::PortFlags flags)
883 {
884         if (name.size () == 0) { return 0; }
885         if (flags & IsPhysical) { return 0; }
886         return add_port (_instance_name + ":" + name, type, flags);
887 }
888
889 PortEngine::PortHandle
890 AlsaAudioBackend::add_port (
891                 const std::string& name,
892                 ARDOUR::DataType type,
893                 ARDOUR::PortFlags flags)
894 {
895         assert(name.size ());
896         if (find_port (name)) {
897                 PBD::error << _("AlsaBackend::register_port: Port already exists:")
898                                 << " (" << name << ")" << endmsg;
899                 return 0;
900         }
901         AlsaPort* port = NULL;
902         switch (type) {
903                 case DataType::AUDIO:
904                         port = new AlsaAudioPort (*this, name, flags);
905                         break;
906                 case DataType::MIDI:
907                         port = new AlsaMidiPort (*this, name, flags);
908                         break;
909                 default:
910                         PBD::error << _("AlsaBackend::register_port: Invalid Data Type.") << endmsg;
911                         return 0;
912         }
913
914         _ports.push_back (port);
915
916         return port;
917 }
918
919 void
920 AlsaAudioBackend::unregister_port (PortEngine::PortHandle port_handle)
921 {
922         if (!_run) {
923                 return;
924         }
925         AlsaPort* port = static_cast<AlsaPort*>(port_handle);
926         std::vector<AlsaPort*>::iterator i = std::find (_ports.begin (), _ports.end (), static_cast<AlsaPort*>(port_handle));
927         if (i == _ports.end ()) {
928                 PBD::error << _("AlsaBackend::unregister_port: Failed to find port") << endmsg;
929                 return;
930         }
931         disconnect_all(port_handle);
932         _ports.erase (i);
933         delete port;
934 }
935
936 int
937 AlsaAudioBackend::register_system_audio_ports()
938 {
939         LatencyRange lr;
940
941         const int a_ins = _n_inputs > 0 ? _n_inputs : 2;
942         const int a_out = _n_outputs > 0 ? _n_outputs : 2;
943
944         /* audio ports */
945         lr.min = lr.max = _samples_per_period + (_measure_latency ? 0 : _systemic_audio_input_latency);
946         for (int i = 1; i <= a_ins; ++i) {
947                 char tmp[64];
948                 snprintf(tmp, sizeof(tmp), "system:capture_%d", i);
949                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
950                 if (!p) return -1;
951                 set_latency_range (p, false, lr);
952                 _system_inputs.push_back(static_cast<AlsaPort*>(p));
953         }
954
955         lr.min = lr.max = _samples_per_period + (_measure_latency ? 0 : _systemic_audio_output_latency);
956         for (int i = 1; i <= a_out; ++i) {
957                 char tmp[64];
958                 snprintf(tmp, sizeof(tmp), "system:playback_%d", i);
959                 PortHandle p = add_port(std::string(tmp), DataType::AUDIO, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
960                 if (!p) return -1;
961                 set_latency_range (p, true, lr);
962                 _system_outputs.push_back(static_cast<AlsaPort*>(p));
963         }
964         return 0;
965 }
966
967 int
968 AlsaAudioBackend::register_system_midi_ports()
969 {
970         std::map<std::string, std::string> devices;
971         int midi_ins = 0;
972         int midi_outs = 0;
973
974         if (_midi_driver_option == _("None")) {
975                 return 0;
976         } else if (_midi_driver_option == _("ALSA raw devices")) {
977                 get_alsa_rawmidi_device_names(devices);
978         } else {
979                 get_alsa_sequencer_names (devices);
980         }
981
982         for (std::map<std::string, std::string>::const_iterator i = devices.begin (); i != devices.end(); ++i) {
983                 struct AlsaMidiDeviceInfo * nfo = midi_device_info(i->first);
984                 if (!nfo) continue;
985                 if (!nfo->enabled) continue;
986
987                 AlsaMidiOut *mout;
988                 if (_midi_driver_option == _("ALSA raw devices")) {
989                         mout = new AlsaRawMidiOut (i->second.c_str());
990                 } else {
991                         mout = new AlsaSeqMidiOut (i->second.c_str());
992                 }
993
994                 if (mout->state ()) {
995                         PBD::warning << string_compose (
996                                         _("AlsaMidiOut: failed to open midi device '%1'."), i->second)
997                                 << endmsg;
998                         delete mout;
999                 } else {
1000                         mout->setup_timing(_samples_per_period, _samplerate);
1001                         mout->sync_time (g_get_monotonic_time());
1002                         if (mout->start ()) {
1003                                 PBD::warning << string_compose (
1004                                                 _("AlsaMidiOut: failed to start midi device '%1'."), i->second)
1005                                         << endmsg;
1006                                 delete mout;
1007                         } else {
1008                                 char tmp[64];
1009                                 snprintf(tmp, sizeof(tmp), "system:midi_playback_%d", ++midi_ins);
1010                                 PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsInput | IsPhysical | IsTerminal));
1011                                 if (!p) {
1012                                         mout->stop();
1013                                         delete mout;
1014                                 }
1015                                 LatencyRange lr;
1016                                 lr.min = lr.max = _samples_per_period + (_measure_latency ? 0 : nfo->systemic_output_latency);
1017                                 set_latency_range (p, false, lr);
1018                                 static_cast<AlsaMidiPort*>(p)->set_n_periods(2);
1019                                 _system_midi_out.push_back(static_cast<AlsaPort*>(p));
1020                                 _rmidi_out.push_back (mout);
1021                         }
1022                 }
1023
1024                 AlsaMidiIn *midin;
1025                 if (_midi_driver_option == _("ALSA raw devices")) {
1026                         midin = new AlsaRawMidiIn (i->second.c_str());
1027                 } else {
1028                         midin = new AlsaSeqMidiIn (i->second.c_str());
1029                 }
1030
1031                 if (midin->state ()) {
1032                         PBD::warning << string_compose (
1033                                         _("AlsaMidiIn: failed to open midi device '%1'."), i->second)
1034                                 << endmsg;
1035                         delete midin;
1036                 } else {
1037                         midin->setup_timing(_samples_per_period, _samplerate);
1038                         midin->sync_time (g_get_monotonic_time());
1039                         if (midin->start ()) {
1040                                 PBD::warning << string_compose (
1041                                                 _("AlsaMidiIn: failed to start midi device '%1'."), i->second)
1042                                         << endmsg;
1043                                 delete midin;
1044                         } else {
1045                                 char tmp[64];
1046                                 snprintf(tmp, sizeof(tmp), "system:midi_capture_%d", ++midi_outs);
1047                                 PortHandle p = add_port(std::string(tmp), DataType::MIDI, static_cast<PortFlags>(IsOutput | IsPhysical | IsTerminal));
1048                                 if (!p) {
1049                                         midin->stop();
1050                                         delete midin;
1051                                         continue;
1052                                 }
1053                                 LatencyRange lr;
1054                                 lr.min = lr.max = _samples_per_period + (_measure_latency ? 0 : nfo->systemic_input_latency);
1055                                 set_latency_range (p, false, lr);
1056                                 _system_midi_in.push_back(static_cast<AlsaPort*>(p));
1057                                 _rmidi_in.push_back (midin);
1058                         }
1059                 }
1060         }
1061         return 0;
1062 }
1063
1064 void
1065 AlsaAudioBackend::unregister_ports (bool system_only)
1066 {
1067         size_t i = 0;
1068         _system_inputs.clear();
1069         _system_outputs.clear();
1070         _system_midi_in.clear();
1071         _system_midi_out.clear();
1072         while (i <  _ports.size ()) {
1073                 AlsaPort* port = _ports[i];
1074                 if (! system_only || (port->is_physical () && port->is_terminal ())) {
1075                         port->disconnect_all ();
1076                         delete port;
1077                         _ports.erase (_ports.begin() + i);
1078                 } else {
1079                         ++i;
1080                 }
1081         }
1082 }
1083
1084 int
1085 AlsaAudioBackend::connect (const std::string& src, const std::string& dst)
1086 {
1087         AlsaPort* src_port = find_port (src);
1088         AlsaPort* dst_port = find_port (dst);
1089
1090         if (!src_port) {
1091                 PBD::error << _("AlsaBackend::connect: Invalid Source port:")
1092                                 << " (" << src <<")" << endmsg;
1093                 return -1;
1094         }
1095         if (!dst_port) {
1096                 PBD::error << _("AlsaBackend::connect: Invalid Destination port:")
1097                         << " (" << dst <<")" << endmsg;
1098                 return -1;
1099         }
1100         return src_port->connect (dst_port);
1101 }
1102
1103 int
1104 AlsaAudioBackend::disconnect (const std::string& src, const std::string& dst)
1105 {
1106         AlsaPort* src_port = find_port (src);
1107         AlsaPort* dst_port = find_port (dst);
1108
1109         if (!src_port || !dst_port) {
1110                 PBD::error << _("AlsaBackend::disconnect: Invalid Port(s)") << endmsg;
1111                 return -1;
1112         }
1113         return src_port->disconnect (dst_port);
1114 }
1115
1116 int
1117 AlsaAudioBackend::connect (PortEngine::PortHandle src, const std::string& dst)
1118 {
1119         AlsaPort* dst_port = find_port (dst);
1120         if (!valid_port (src)) {
1121                 PBD::error << _("AlsaBackend::connect: Invalid Source Port Handle") << endmsg;
1122                 return -1;
1123         }
1124         if (!dst_port) {
1125                 PBD::error << _("AlsaBackend::connect: Invalid Destination Port")
1126                         << " (" << dst << ")" << endmsg;
1127                 return -1;
1128         }
1129         return static_cast<AlsaPort*>(src)->connect (dst_port);
1130 }
1131
1132 int
1133 AlsaAudioBackend::disconnect (PortEngine::PortHandle src, const std::string& dst)
1134 {
1135         AlsaPort* dst_port = find_port (dst);
1136         if (!valid_port (src) || !dst_port) {
1137                 PBD::error << _("AlsaBackend::disconnect: Invalid Port(s)") << endmsg;
1138                 return -1;
1139         }
1140         return static_cast<AlsaPort*>(src)->disconnect (dst_port);
1141 }
1142
1143 int
1144 AlsaAudioBackend::disconnect_all (PortEngine::PortHandle port)
1145 {
1146         if (!valid_port (port)) {
1147                 PBD::error << _("AlsaBackend::disconnect_all: Invalid Port") << endmsg;
1148                 return -1;
1149         }
1150         static_cast<AlsaPort*>(port)->disconnect_all ();
1151         return 0;
1152 }
1153
1154 bool
1155 AlsaAudioBackend::connected (PortEngine::PortHandle port, bool /* process_callback_safe*/)
1156 {
1157         if (!valid_port (port)) {
1158                 PBD::error << _("AlsaBackend::disconnect_all: Invalid Port") << endmsg;
1159                 return false;
1160         }
1161         return static_cast<AlsaPort*>(port)->is_connected ();
1162 }
1163
1164 bool
1165 AlsaAudioBackend::connected_to (PortEngine::PortHandle src, const std::string& dst, bool /*process_callback_safe*/)
1166 {
1167         AlsaPort* dst_port = find_port (dst);
1168         if (!valid_port (src) || !dst_port) {
1169                 PBD::error << _("AlsaBackend::connected_to: Invalid Port") << endmsg;
1170                 return false;
1171         }
1172         return static_cast<AlsaPort*>(src)->is_connected (dst_port);
1173 }
1174
1175 bool
1176 AlsaAudioBackend::physically_connected (PortEngine::PortHandle port, bool /*process_callback_safe*/)
1177 {
1178         if (!valid_port (port)) {
1179                 PBD::error << _("AlsaBackend::physically_connected: Invalid Port") << endmsg;
1180                 return false;
1181         }
1182         return static_cast<AlsaPort*>(port)->is_physically_connected ();
1183 }
1184
1185 int
1186 AlsaAudioBackend::get_connections (PortEngine::PortHandle port, std::vector<std::string>& names, bool /*process_callback_safe*/)
1187 {
1188         if (!valid_port (port)) {
1189                 PBD::error << _("AlsaBackend::get_connections: Invalid Port") << endmsg;
1190                 return -1;
1191         }
1192
1193         assert (0 == names.size ());
1194
1195         const std::vector<AlsaPort*>& connected_ports = static_cast<AlsaPort*>(port)->get_connections ();
1196
1197         for (std::vector<AlsaPort*>::const_iterator i = connected_ports.begin (); i != connected_ports.end (); ++i) {
1198                 names.push_back ((*i)->name ());
1199         }
1200
1201         return (int)names.size ();
1202 }
1203
1204 /* MIDI */
1205 int
1206 AlsaAudioBackend::midi_event_get (
1207                 pframes_t& timestamp,
1208                 size_t& size, uint8_t** buf, void* port_buffer,
1209                 uint32_t event_index)
1210 {
1211         assert (buf && port_buffer);
1212         AlsaMidiBuffer& source = * static_cast<AlsaMidiBuffer*>(port_buffer);
1213         if (event_index >= source.size ()) {
1214                 return -1;
1215         }
1216         AlsaMidiEvent * const event = source[event_index].get ();
1217
1218         timestamp = event->timestamp ();
1219         size = event->size ();
1220         *buf = event->data ();
1221         return 0;
1222 }
1223
1224 int
1225 AlsaAudioBackend::midi_event_put (
1226                 void* port_buffer,
1227                 pframes_t timestamp,
1228                 const uint8_t* buffer, size_t size)
1229 {
1230         assert (buffer && port_buffer);
1231         AlsaMidiBuffer& dst = * static_cast<AlsaMidiBuffer*>(port_buffer);
1232         if (dst.size () && (pframes_t)dst.back ()->timestamp () > timestamp) {
1233                 fprintf (stderr, "AlsaMidiBuffer: it's too late for this event. %d > %d\n",
1234                                 (pframes_t)dst.back ()->timestamp (), timestamp);
1235                 return -1;
1236         }
1237         dst.push_back (boost::shared_ptr<AlsaMidiEvent>(new AlsaMidiEvent (timestamp, buffer, size)));
1238         return 0;
1239 }
1240
1241 uint32_t
1242 AlsaAudioBackend::get_midi_event_count (void* port_buffer)
1243 {
1244         assert (port_buffer);
1245         return static_cast<AlsaMidiBuffer*>(port_buffer)->size ();
1246 }
1247
1248 void
1249 AlsaAudioBackend::midi_clear (void* port_buffer)
1250 {
1251         assert (port_buffer);
1252         AlsaMidiBuffer * buf = static_cast<AlsaMidiBuffer*>(port_buffer);
1253         assert (buf);
1254         buf->clear ();
1255 }
1256
1257 /* Monitoring */
1258
1259 bool
1260 AlsaAudioBackend::can_monitor_input () const
1261 {
1262         return false;
1263 }
1264
1265 int
1266 AlsaAudioBackend::request_input_monitoring (PortEngine::PortHandle, bool)
1267 {
1268         return -1;
1269 }
1270
1271 int
1272 AlsaAudioBackend::ensure_input_monitoring (PortEngine::PortHandle, bool)
1273 {
1274         return -1;
1275 }
1276
1277 bool
1278 AlsaAudioBackend::monitoring_input (PortEngine::PortHandle)
1279 {
1280         return false;
1281 }
1282
1283 /* Latency management */
1284
1285 void
1286 AlsaAudioBackend::set_latency_range (PortEngine::PortHandle port, bool for_playback, LatencyRange latency_range)
1287 {
1288         if (!valid_port (port)) {
1289                 PBD::error << _("AlsaPort::set_latency_range (): invalid port.") << endmsg;
1290         }
1291         static_cast<AlsaPort*>(port)->set_latency_range (latency_range, for_playback);
1292 }
1293
1294 LatencyRange
1295 AlsaAudioBackend::get_latency_range (PortEngine::PortHandle port, bool for_playback)
1296 {
1297         if (!valid_port (port)) {
1298                 PBD::error << _("AlsaPort::get_latency_range (): invalid port.") << endmsg;
1299                 LatencyRange r;
1300                 r.min = 0;
1301                 r.max = 0;
1302                 return r;
1303         }
1304         return static_cast<AlsaPort*>(port)->latency_range (for_playback);
1305 }
1306
1307 /* Discovering physical ports */
1308
1309 bool
1310 AlsaAudioBackend::port_is_physical (PortEngine::PortHandle port) const
1311 {
1312         if (!valid_port (port)) {
1313                 PBD::error << _("AlsaPort::port_is_physical (): invalid port.") << endmsg;
1314                 return false;
1315         }
1316         return static_cast<AlsaPort*>(port)->is_physical ();
1317 }
1318
1319 void
1320 AlsaAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>& port_names)
1321 {
1322         for (size_t i = 0; i < _ports.size (); ++i) {
1323                 AlsaPort* port = _ports[i];
1324                 if ((port->type () == type) && port->is_input () && port->is_physical ()) {
1325                         port_names.push_back (port->name ());
1326                 }
1327         }
1328 }
1329
1330 void
1331 AlsaAudioBackend::get_physical_inputs (DataType type, std::vector<std::string>& port_names)
1332 {
1333         for (size_t i = 0; i < _ports.size (); ++i) {
1334                 AlsaPort* port = _ports[i];
1335                 if ((port->type () == type) && port->is_output () && port->is_physical ()) {
1336                         port_names.push_back (port->name ());
1337                 }
1338         }
1339 }
1340
1341 ChanCount
1342 AlsaAudioBackend::n_physical_outputs () const
1343 {
1344         int n_midi = 0;
1345         int n_audio = 0;
1346         for (size_t i = 0; i < _ports.size (); ++i) {
1347                 AlsaPort* port = _ports[i];
1348                 if (port->is_output () && port->is_physical ()) {
1349                         switch (port->type ()) {
1350                                 case DataType::AUDIO: ++n_audio; break;
1351                                 case DataType::MIDI: ++n_midi; break;
1352                                 default: break;
1353                         }
1354                 }
1355         }
1356         ChanCount cc;
1357         cc.set (DataType::AUDIO, n_audio);
1358         cc.set (DataType::MIDI, n_midi);
1359         return cc;
1360 }
1361
1362 ChanCount
1363 AlsaAudioBackend::n_physical_inputs () const
1364 {
1365         int n_midi = 0;
1366         int n_audio = 0;
1367         for (size_t i = 0; i < _ports.size (); ++i) {
1368                 AlsaPort* port = _ports[i];
1369                 if (port->is_input () && port->is_physical ()) {
1370                         switch (port->type ()) {
1371                                 case DataType::AUDIO: ++n_audio; break;
1372                                 case DataType::MIDI: ++n_midi; break;
1373                                 default: break;
1374                         }
1375                 }
1376         }
1377         ChanCount cc;
1378         cc.set (DataType::AUDIO, n_audio);
1379         cc.set (DataType::MIDI, n_midi);
1380         return cc;
1381 }
1382
1383 /* Getting access to the data buffer for a port */
1384
1385 void*
1386 AlsaAudioBackend::get_buffer (PortEngine::PortHandle port, pframes_t nframes)
1387 {
1388         assert (port);
1389         assert (valid_port (port));
1390         return static_cast<AlsaPort*>(port)->get_buffer (nframes);
1391 }
1392
1393 /* Engine Process */
1394 void *
1395 AlsaAudioBackend::main_process_thread ()
1396 {
1397         AudioEngine::thread_init_callback (this);
1398         _active = true;
1399         _processed_samples = 0;
1400
1401         uint64_t clock1, clock2;
1402         clock1 = g_get_monotonic_time();
1403         _pcmi->pcm_start ();
1404         int no_proc_errors = 0;
1405         const int bailout = 2 * _samplerate / _samples_per_period;
1406         const int64_t nomial_time = 1e6 * _samples_per_period / _samplerate;
1407
1408         manager.registration_callback();
1409         manager.graph_order_callback();
1410
1411         while (_run) {
1412                 long nr;
1413                 bool xrun = false;
1414                 if (!_freewheeling) {
1415                         nr = _pcmi->pcm_wait ();
1416
1417                         if (_pcmi->state () > 0) {
1418                                 ++no_proc_errors;
1419                                 xrun = true;
1420                         }
1421                         if (_pcmi->state () < 0 || no_proc_errors > bailout) {
1422                                 PBD::error << _("AlsaAudioBackend: I/O error. Audio Process Terminated.") << endmsg;
1423                                 break;
1424                         }
1425                         while (nr >= (long)_samples_per_period) {
1426                                 uint32_t i = 0;
1427                                 clock1 = g_get_monotonic_time();
1428                                 no_proc_errors = 0;
1429
1430                                 _pcmi->capt_init (_samples_per_period);
1431                                 for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it, ++i) {
1432                                         _pcmi->capt_chan (i, (float*)((*it)->get_buffer(_samples_per_period)), _samples_per_period);
1433                                 }
1434                                 _pcmi->capt_done (_samples_per_period);
1435
1436                                 /* de-queue midi*/
1437                                 i = 0;
1438                                 for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) {
1439                                         assert (_rmidi_in.size() > i);
1440                                         AlsaMidiIn *rm = _rmidi_in.at(i);
1441                                         void *bptr = (*it)->get_buffer(0);
1442                                         pframes_t time;
1443                                         uint8_t data[64]; // match MaxAlsaEventSize in alsa_rawmidi.cc
1444                                         size_t size = sizeof(data);
1445                                         midi_clear(bptr);
1446                                         while (rm->recv_event (time, data, size)) {
1447                                                 midi_event_put(bptr, time, data, size);
1448                                                 size = sizeof(data);
1449                                         }
1450                                         rm->sync_time (clock1);
1451                                 }
1452
1453                                 for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) {
1454                                         memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
1455                                 }
1456
1457                                 if (engine.process_callback (_samples_per_period)) {
1458                                         _pcmi->pcm_stop ();
1459                                         _active = false;
1460                                         return 0;
1461                                 }
1462
1463                                 i = 0;
1464                                 for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
1465                                         static_cast<AlsaMidiPort*>(*it)->next_period();
1466                                 }
1467
1468                                 /* queue midi */
1469                                 i = 0;
1470                                 for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
1471                                         assert (_rmidi_out.size() > i);
1472                                         const AlsaMidiBuffer src = static_cast<const AlsaMidiPort*>(*it)->const_buffer();
1473                                         AlsaMidiOut *rm = _rmidi_out.at(i);
1474                                         rm->sync_time (clock1);
1475                                         for (AlsaMidiBuffer::const_iterator mit = src.begin (); mit != src.end (); ++mit) {
1476                                                 rm->send_event ((*mit)->timestamp(), (*mit)->data(), (*mit)->size());
1477                                         }
1478                                 }
1479
1480                                 /* write back audio */
1481                                 i = 0;
1482                                 _pcmi->play_init (_samples_per_period);
1483                                 for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it, ++i) {
1484                                         _pcmi->play_chan (i, (const float*)(*it)->get_buffer (_samples_per_period), _samples_per_period);
1485                                 }
1486                                 for (; i < _pcmi->nplay (); ++i) {
1487                                         _pcmi->clear_chan (i, _samples_per_period);
1488                                 }
1489                                 _pcmi->play_done (_samples_per_period);
1490                                 nr -= _samples_per_period;
1491                                 _processed_samples += _samples_per_period;
1492
1493                                 /* calculate DSP load */
1494                                 clock2 = g_get_monotonic_time();
1495                                 const int64_t elapsed_time = clock2 - clock1;
1496                                 _dsp_load = elapsed_time / (float) nomial_time;
1497                         }
1498
1499                         if (xrun && (_pcmi->capt_xrun() > 0 || _pcmi->play_xrun() > 0)) {
1500                                 engine.Xrun ();
1501 #if 0
1502                                 fprintf(stderr, "ALSA x-run read: %.1f ms, write: %.1f ms\n",
1503                                                 _pcmi->capt_xrun() * 1000.0, _pcmi->play_xrun() * 1000.0);
1504 #endif
1505                         }
1506                 } else {
1507                         // Freewheelin'
1508                         for (std::vector<AlsaPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
1509                                 memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
1510                         }
1511                         for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) {
1512                                 static_cast<AlsaMidiBuffer*>((*it)->get_buffer(0))->clear ();
1513                         }
1514
1515                         if (engine.process_callback (_samples_per_period)) {
1516                                 _pcmi->pcm_stop ();
1517                                 return 0;
1518                         }
1519                         _dsp_load = 1.0;
1520                         Glib::usleep (100); // don't hog cpu
1521                 }
1522
1523                 bool connections_changed = false;
1524                 bool ports_changed = false;
1525                 if (!pthread_mutex_trylock (&_port_callback_mutex)) {
1526                         if (_port_change_flag) {
1527                                 ports_changed = true;
1528                                 _port_change_flag = false;
1529                         }
1530                         if (!_port_connection_queue.empty ()) {
1531                                 connections_changed = true;
1532                         }
1533                         while (!_port_connection_queue.empty ()) {
1534                                 PortConnectData *c = _port_connection_queue.back ();
1535                                 manager.connect_callback (c->a, c->b, c->c);
1536                                 _port_connection_queue.pop_back ();
1537                                 delete c;
1538                         }
1539                         pthread_mutex_unlock (&_port_callback_mutex);
1540                 }
1541                 if (ports_changed) {
1542                         manager.registration_callback();
1543                 }
1544                 if (connections_changed) {
1545                         manager.graph_order_callback();
1546                 }
1547                 if (connections_changed || ports_changed) {
1548                         engine.latency_callback(false);
1549                         engine.latency_callback(true);
1550                 }
1551
1552         }
1553         _pcmi->pcm_stop ();
1554         _active = false;
1555         if (_run) {
1556                 engine.halted_callback("ALSA I/O error.");
1557         }
1558         return 0;
1559 }
1560
1561
1562 /******************************************************************************/
1563
1564 static boost::shared_ptr<AlsaAudioBackend> _instance;
1565
1566 static boost::shared_ptr<AudioBackend> backend_factory (AudioEngine& e);
1567 static int instantiate (const std::string& arg1, const std::string& /* arg2 */);
1568 static int deinstantiate ();
1569 static bool already_configured ();
1570 static bool available ();
1571
1572 static ARDOUR::AudioBackendInfo _descriptor = {
1573         "ALSA",
1574         instantiate,
1575         deinstantiate,
1576         backend_factory,
1577         already_configured,
1578         available
1579 };
1580
1581 static boost::shared_ptr<AudioBackend>
1582 backend_factory (AudioEngine& e)
1583 {
1584         if (!_instance) {
1585                 _instance.reset (new AlsaAudioBackend (e, _descriptor));
1586         }
1587         return _instance;
1588 }
1589
1590 static int
1591 instantiate (const std::string& arg1, const std::string& /* arg2 */)
1592 {
1593         s_instance_name = arg1;
1594         return 0;
1595 }
1596
1597 static int
1598 deinstantiate ()
1599 {
1600         _instance.reset ();
1601         return 0;
1602 }
1603
1604 static bool
1605 already_configured ()
1606 {
1607         return false;
1608 }
1609
1610 static bool
1611 available ()
1612 {
1613         return true;
1614 }
1615
1616 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
1617 {
1618         return &_descriptor;
1619 }
1620
1621
1622 /******************************************************************************/
1623 AlsaPort::AlsaPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
1624         : _alsa_backend (b)
1625         , _name  (name)
1626         , _flags (flags)
1627 {
1628         _capture_latency_range.min = 0;
1629         _capture_latency_range.max = 0;
1630         _playback_latency_range.min = 0;
1631         _playback_latency_range.max = 0;
1632 }
1633
1634 AlsaPort::~AlsaPort () {
1635         disconnect_all ();
1636 }
1637
1638
1639 int AlsaPort::connect (AlsaPort *port)
1640 {
1641         if (!port) {
1642                 PBD::error << _("AlsaPort::connect (): invalid (null) port") << endmsg;
1643                 return -1;
1644         }
1645
1646         if (type () != port->type ()) {
1647                 PBD::error << _("AlsaPort::connect (): wrong port-type") << endmsg;
1648                 return -1;
1649         }
1650
1651         if (is_output () && port->is_output ()) {
1652                 PBD::error << _("AlsaPort::connect (): cannot inter-connect output ports.") << endmsg;
1653                 return -1;
1654         }
1655
1656         if (is_input () && port->is_input ()) {
1657                 PBD::error << _("AlsaPort::connect (): cannot inter-connect input ports.") << endmsg;
1658                 return -1;
1659         }
1660
1661         if (this == port) {
1662                 PBD::error << _("AlsaPort::connect (): cannot self-connect ports.") << endmsg;
1663                 return -1;
1664         }
1665
1666         if (is_connected (port)) {
1667 #if 0 // don't bother to warn about this for now. just ignore it
1668                 PBD::error << _("AlsaPort::connect (): ports are already connected:")
1669                         << " (" << name () << ") -> (" << port->name () << ")"
1670                         << endmsg;
1671 #endif
1672                 return -1;
1673         }
1674
1675         _connect (port, true);
1676         return 0;
1677 }
1678
1679
1680 void AlsaPort::_connect (AlsaPort *port, bool callback)
1681 {
1682         _connections.push_back (port);
1683         if (callback) {
1684                 port->_connect (this, false);
1685                 _alsa_backend.port_connect_callback (name(),  port->name(), true);
1686         }
1687 }
1688
1689 int AlsaPort::disconnect (AlsaPort *port)
1690 {
1691         if (!port) {
1692                 PBD::error << _("AlsaPort::disconnect (): invalid (null) port") << endmsg;
1693                 return -1;
1694         }
1695
1696         if (!is_connected (port)) {
1697                 PBD::error << _("AlsaPort::disconnect (): ports are not connected:")
1698                         << " (" << name () << ") -> (" << port->name () << ")"
1699                         << endmsg;
1700                 return -1;
1701         }
1702         _disconnect (port, true);
1703         return 0;
1704 }
1705
1706 void AlsaPort::_disconnect (AlsaPort *port, bool callback)
1707 {
1708         std::vector<AlsaPort*>::iterator it = std::find (_connections.begin (), _connections.end (), port);
1709
1710         assert (it != _connections.end ());
1711
1712         _connections.erase (it);
1713
1714         if (callback) {
1715                 port->_disconnect (this, false);
1716                 _alsa_backend.port_connect_callback (name(),  port->name(), false);
1717         }
1718 }
1719
1720
1721 void AlsaPort::disconnect_all ()
1722 {
1723         while (!_connections.empty ()) {
1724                 _connections.back ()->_disconnect (this, false);
1725                 _alsa_backend.port_connect_callback (name(),  _connections.back ()->name(), false);
1726                 _connections.pop_back ();
1727         }
1728 }
1729
1730 bool
1731 AlsaPort::is_connected (const AlsaPort *port) const
1732 {
1733         return std::find (_connections.begin (), _connections.end (), port) != _connections.end ();
1734 }
1735
1736 bool AlsaPort::is_physically_connected () const
1737 {
1738         for (std::vector<AlsaPort*>::const_iterator it = _connections.begin (); it != _connections.end (); ++it) {
1739                 if ((*it)->is_physical ()) {
1740                         return true;
1741                 }
1742         }
1743         return false;
1744 }
1745
1746 /******************************************************************************/
1747
1748 AlsaAudioPort::AlsaAudioPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
1749         : AlsaPort (b, name, flags)
1750 {
1751         memset (_buffer, 0, sizeof (_buffer));
1752         mlock(_buffer, sizeof (_buffer));
1753 }
1754
1755 AlsaAudioPort::~AlsaAudioPort () { }
1756
1757 void* AlsaAudioPort::get_buffer (pframes_t n_samples)
1758 {
1759         if (is_input ()) {
1760                 std::vector<AlsaPort*>::const_iterator it = get_connections ().begin ();
1761                 if (it == get_connections ().end ()) {
1762                         memset (_buffer, 0, n_samples * sizeof (Sample));
1763                 } else {
1764                         AlsaAudioPort const * source = static_cast<const AlsaAudioPort*>(*it);
1765                         assert (source && source->is_output ());
1766                         memcpy (_buffer, source->const_buffer (), n_samples * sizeof (Sample));
1767                         while (++it != get_connections ().end ()) {
1768                                 source = static_cast<const AlsaAudioPort*>(*it);
1769                                 assert (source && source->is_output ());
1770                                 Sample* dst = buffer ();
1771                                 const Sample* src = source->const_buffer ();
1772                                 for (uint32_t s = 0; s < n_samples; ++s, ++dst, ++src) {
1773                                         *dst += *src;
1774                                 }
1775                         }
1776                 }
1777         }
1778         return _buffer;
1779 }
1780
1781
1782 AlsaMidiPort::AlsaMidiPort (AlsaAudioBackend &b, const std::string& name, PortFlags flags)
1783         : AlsaPort (b, name, flags)
1784         , _n_periods (1)
1785         , _bufperiod (0)
1786 {
1787         _buffer[0].clear ();
1788         _buffer[1].clear ();
1789 }
1790
1791 AlsaMidiPort::~AlsaMidiPort () { }
1792
1793 struct MidiEventSorter {
1794         bool operator() (const boost::shared_ptr<AlsaMidiEvent>& a, const boost::shared_ptr<AlsaMidiEvent>& b) {
1795                 return *a < *b;
1796         }
1797 };
1798
1799 void* AlsaMidiPort::get_buffer (pframes_t /* nframes */)
1800 {
1801         if (is_input ()) {
1802                 (_buffer[_bufperiod]).clear ();
1803                 for (std::vector<AlsaPort*>::const_iterator i = get_connections ().begin ();
1804                                 i != get_connections ().end ();
1805                                 ++i) {
1806                         const AlsaMidiBuffer src = static_cast<const AlsaMidiPort*>(*i)->const_buffer ();
1807                         for (AlsaMidiBuffer::const_iterator it = src.begin (); it != src.end (); ++it) {
1808                                 (_buffer[_bufperiod]).push_back (boost::shared_ptr<AlsaMidiEvent>(new AlsaMidiEvent (**it)));
1809                         }
1810                 }
1811                 std::sort ((_buffer[_bufperiod]).begin (), (_buffer[_bufperiod]).end (), MidiEventSorter());
1812         }
1813         return &(_buffer[_bufperiod]);
1814 }
1815
1816 AlsaMidiEvent::AlsaMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size)
1817         : _size (size)
1818         , _timestamp (timestamp)
1819         , _data (0)
1820 {
1821         if (size > 0) {
1822                 _data = (uint8_t*) malloc (size);
1823                 memcpy (_data, data, size);
1824         }
1825 }
1826
1827 AlsaMidiEvent::AlsaMidiEvent (const AlsaMidiEvent& other)
1828         : _size (other.size ())
1829         , _timestamp (other.timestamp ())
1830         , _data (0)
1831 {
1832         if (other.size () && other.const_data ()) {
1833                 _data = (uint8_t*) malloc (other.size ());
1834                 memcpy (_data, other.const_data (), other.size ());
1835         }
1836 };
1837
1838 AlsaMidiEvent::~AlsaMidiEvent () {
1839         free (_data);
1840 };