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