1 /*
2 Copyright (C) 2005-2006 Remon Sijrier
3
4 (December 2005) Ported to C++ for Traverso by Remon Sijrier
5 Copyright (C) 2001 Paul Davis
6
7 This file is part of Traverso
8
9 Traverso is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 */
24
25 /* ALSA driver based on jack-audio-connection-kit-0.109.0 alsa_driver.c */
26
27
28 #include "AlsaDriver.h"
29 #include "AudioChannel.h"
30 #include <Utils.h>
31
32 #include <math.h>
33 #include <stdio.h>
34 #include <memory.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <errno.h>
38 #include <stdarg.h>
39 #include <signal.h>
40 #include <sys/types.h>
41 #include <regex.h>
42
43 #include <string.h>
44 #include <sys/time.h>
45 #include <time.h>
46
47 #include "AudioDevice.h"
48
49 // Always put me below _all_ includes, this is needed
50 // in case we run with memory leak detection enabled!
51 #include "Debugger.h"
52
53 #undef DEBUG_WAKEUP
54
55 /* Delay (in process calls) before Traverso will report an xrun */
56 #define XRUN_REPORT_DELAY 0
57
58
AlsaDriver(AudioDevice * dev,int rate,nframes_t bufferSize)59 AlsaDriver::AlsaDriver(AudioDevice* dev, int rate, nframes_t bufferSize)
60 : Driver(dev, rate, bufferSize)
61 {
62 read = MakeDelegate(this, &AlsaDriver::_read);
63 write = MakeDelegate(this, &AlsaDriver::_write);
64 run_cycle = RunCycleCallback(this, &AlsaDriver::_run_cycle);
65 }
66
~AlsaDriver()67 AlsaDriver::~AlsaDriver()
68 {
69 PENTERDES;
70 if (capture_handle) {
71 snd_pcm_close (capture_handle);
72 }
73
74 if (playback_handle) {
75 snd_pcm_close (playback_handle);
76 }
77
78 if (capture_hw_params) {
79 snd_pcm_hw_params_free (capture_hw_params);
80 }
81
82 if (playback_hw_params) {
83 snd_pcm_hw_params_free (playback_hw_params);
84 }
85
86 if (capture_sw_params) {
87 snd_pcm_sw_params_free (capture_sw_params);
88 }
89
90 if (playback_sw_params) {
91 snd_pcm_sw_params_free (playback_sw_params);
92 }
93
94 if (pfd) {
95 free (pfd);
96 }
97
98 release_channel_dependent_memory ();
99 }
100
101
setup(bool capture,bool playback,const QString & pcmName,const QString & ditherShape)102 int AlsaDriver::setup(bool capture, bool playback, const QString& pcmName, const QString& ditherShape)
103 {
104 unsigned long user_nperiods = device->get_driver_property("numberofperiods", 3).toInt();
105 char *playback_pcm_name = strdup(pcmName.toLatin1().data());
106 char *capture_pcm_name = strdup(pcmName.toLatin1().data());
107 int shorts_first = false;
108
109 /* duplex is the default */
110 if (!capture && !playback) {
111 capture = true;
112 playback = true;
113 }
114
115
116 int err;
117 playback_handle = (snd_pcm_t*) 0;
118 capture_handle = (snd_pcm_t*) 0;
119 ctl_handle = 0;
120 capture_and_playback_not_synced = false;
121 capture_interleaved = false;
122 playback_interleaved = false;
123 max_nchannels = 0;
124 user_nchannels = 0;
125 playback_nchannels = 0;
126 capture_nchannels = 0;
127 playback_sample_bytes = (shorts_first ? 2:4);
128 capture_sample_bytes = (shorts_first ? 2:4);
129 capture_frame_latency = 0;
130 playback_frame_latency = 0;
131 channels_done = 0;
132 channels_not_done = 0;
133 dither_state = 0;
134
135 playback_addr = 0;
136 capture_addr = 0;
137 playback_interleave_skip = NULL;
138 capture_interleave_skip = NULL;
139
140
141 playback_hw_params = 0;
142 capture_hw_params = 0;
143 playback_sw_params = 0;
144 capture_sw_params = 0;
145
146
147 silent = 0;
148
149 pfd = 0;
150 playback_nfds = 0;
151 capture_nfds = 0;
152
153 if (ditherShape == "Rectangular") {
154 dither = Rectangular;
155 } else if (ditherShape == "Shaped") {
156 dither = Shaped;
157 } else if (ditherShape == "Triangular") {
158 dither = Triangular;
159 } else {
160 dither = None;
161 }
162
163 soft_mode = false;
164
165 quirk_bswap = 0;
166
167 process_count = 0;
168
169 alsa_name_playback = strdup (playback_pcm_name);
170 alsa_name_capture = strdup (capture_pcm_name);
171
172
173 printf ("creating alsa driver ... %s|%s|%d|%lu|%d|%d|%d|%s|%s\n",
174 playback ? playback_pcm_name : "-",
175 capture ? capture_pcm_name : "-",
176 frames_per_cycle, user_nperiods, frame_rate,
177 (int)capture_nchannels, (int)playback_nchannels,
178 soft_mode ? "soft-mode":"-",
179 shorts_first ? "16bit":"32bit");
180
181
182 if (playback) {
183 if (snd_pcm_open (&playback_handle, alsa_name_playback, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) {
184 switch (errno) {
185 case EBUSY:
186 device->message(tr("ALSA Driver: The playback device %1 is already in use. Please stop the"
187 " application using it and run Traverso again").arg(playback_pcm_name), AudioDevice::INFO);
188 return -1;
189 break;
190
191 case EPERM:
192 device->message(tr("ALSA Driver: You do not have permission to open the audio device %1 for playback").arg(playback_pcm_name), AudioDevice::INFO);
193 return -1;
194 break;
195 default:
196 device->message(tr("snd_pcm_open(playback_handle, ..) failed with unknown error type"), AudioDevice::WARNING);
197 }
198
199 playback_handle = 0;
200 }
201
202 if (playback_handle) {
203 snd_pcm_nonblock (playback_handle, 0);
204 }
205 }
206
207 if (capture) {
208 if (snd_pcm_open (&capture_handle, alsa_name_capture, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) < 0) {
209 switch (errno) {
210 case EBUSY:
211 device->message(tr("ALSA Driver: The capture device %1 is already in use. Please stop the"
212 " application using it and run Traverso again").arg(capture_pcm_name), AudioDevice::INFO);
213 return -1;
214 break;
215
216 case EPERM:
217 device->message(tr("ALSA Driver: You do not have permission to open the audio device %1 for capture").arg(capture_pcm_name), AudioDevice::WARNING);
218 return -1;
219 break;
220 default:
221 device->message(tr("ALSA Driver: snd_pcm_open(capture_handle, ...) failed with unknown error type"), AudioDevice::WARNING);
222 }
223
224 capture_handle = 0;
225 }
226
227 if (capture_handle) {
228 snd_pcm_nonblock (capture_handle, 0);
229 }
230 }
231
232 if (playback_handle == 0) {
233 if (playback) {
234
235 /* they asked for playback, but we can't do it */
236
237 device->message(tr("ALSA Driver: Cannot open PCM device %1 for playback. Falling back to capture-only mode").arg("alsa_pcm"), AudioDevice::WARNING);
238
239 if (capture_handle == 0) {
240 /* can't do anything */
241 return -1;
242 }
243 playback = false;
244 }
245 }
246
247 if (capture_handle == 0) {
248 if (capture) {
249
250 /* they asked for capture, but we can't do it */
251
252 device->message(tr("ALSA: Cannot open PCM device %1 for capture. Falling back to playback-only mode").arg("alsa_pcm"), AudioDevice::WARNING);
253
254 if (playback_handle == 0) {
255 /* can't do anything */
256 return -1;
257 }
258 capture = false;
259 }
260 }
261
262
263 if (playback_handle) {
264 if ((err = snd_pcm_hw_params_malloc (&playback_hw_params)) < 0) {
265 PWARN ("ALSA: could not allocate playback hw params structure");
266 return -1;
267 }
268
269 if ((err = snd_pcm_sw_params_malloc (&playback_sw_params)) < 0) {
270 PWARN ("ALSA: could not allocate playback sw params structure");
271 return -1;
272 }
273 }
274
275 if (capture_handle) {
276 if ((err = snd_pcm_hw_params_malloc (&capture_hw_params)) < 0) {
277 PWARN ("ALSA: could not allocate capture hw params structure");
278 return -1;
279 }
280
281 if ((err = snd_pcm_sw_params_malloc (&capture_sw_params)) < 0) {
282 PWARN ("ALSA: could not allocate capture sw params structure");
283 return -1;
284 }
285 }
286
287
288
289 if (set_parameters (frames_per_cycle, user_nperiods, frame_rate)) {
290 return -1;
291 }
292
293 capture_and_playback_not_synced = false;
294
295 if (capture_handle && playback_handle) {
296 if (snd_pcm_link (playback_handle, capture_handle) != 0) {
297 capture_and_playback_not_synced = true;
298 }
299 }
300
301
302 return 1;
303 }
304
305
306
release_channel_dependent_memory()307 void AlsaDriver::release_channel_dependent_memory ()
308 {
309 bitset_destroy (&channels_done);
310 bitset_destroy (&channels_not_done);
311
312 if (playback_addr) {
313 free(playback_addr);
314 playback_addr = 0;
315 }
316
317 if (capture_addr) {
318 free(capture_addr);
319 capture_addr = 0;
320 }
321
322 if (playback_interleave_skip) {
323 free (playback_interleave_skip);
324 playback_interleave_skip = NULL;
325 }
326
327 if (capture_interleave_skip) {
328 free (capture_interleave_skip);
329 capture_interleave_skip = NULL;
330 }
331
332
333 if (silent) {
334 free(silent);
335 silent = 0;
336 }
337
338 if (dither_state) {
339 free(dither_state);
340 dither_state = 0;
341 }
342 }
343
344
setup_io_function_pointers()345 void AlsaDriver::setup_io_function_pointers()
346 {
347 switch (playback_sample_bytes) {
348 case 2:
349 if (playback_interleaved) {
350 channel_copy = memcpy_interleave_d16_s16;
351 } else {
352 channel_copy = memcpy_fake;
353 }
354
355 switch (dither) {
356 case Rectangular:
357 fprintf (stderr,"Rectangular dithering at 16 bits\n");
358 write_via_copy = quirk_bswap?
359 sample_move_dither_rect_d16_sSs:
360 sample_move_dither_rect_d16_sS;
361 break;
362
363 case Triangular:
364 printf("Triangular dithering at 16 bits\n");
365 write_via_copy = quirk_bswap?
366 sample_move_dither_tri_d16_sSs:
367 sample_move_dither_tri_d16_sS;
368 break;
369
370 case Shaped:
371 printf("Noise-shaped dithering at 16 bits\n");
372 write_via_copy = quirk_bswap?
373 sample_move_dither_shaped_d16_sSs:
374 sample_move_dither_shaped_d16_sS;
375 break;
376
377 default:
378 write_via_copy = quirk_bswap?
379 sample_move_d16_sSs : sample_move_d16_sS;
380 break;
381 }
382 break;
383
384 case 3:
385 if (playback_interleaved) {
386 channel_copy = memcpy_interleave_d24_s24;
387 } else {
388 channel_copy = memcpy_fake;
389 }
390
391 switch (dither) {
392 case Rectangular:
393 printf("Rectangular dithering at 24 bits\n");
394 write_via_copy = quirk_bswap?
395 sample_move_dither_rect_d24_sSs:
396 sample_move_dither_rect_d24_sS;
397 break;
398
399 case Triangular:
400 printf("Triangular dithering at 24 bits\n");
401 write_via_copy = quirk_bswap?
402 sample_move_dither_tri_d24_sSs:
403 sample_move_dither_tri_d24_sS;
404 break;
405
406 case Shaped:
407 printf("Noise-shaped dithering at 24 bits\n");
408 write_via_copy = quirk_bswap?
409 sample_move_dither_shaped_d24_sSs:
410 sample_move_dither_shaped_d24_sS;
411 break;
412
413 default:
414 write_via_copy = quirk_bswap?
415 sample_move_d24_sSs : sample_move_d24_sS;
416 break;
417 }
418 break;
419
420 case 4:
421 if (playback_interleaved) {
422 channel_copy = memcpy_interleave_d32_s32;
423 } else {
424 channel_copy = memcpy_fake;
425 }
426
427 switch (dither) {
428 case Rectangular:
429 printf("Rectangular dithering at 32 bits\n");
430 write_via_copy = quirk_bswap?
431 sample_move_dither_rect_d32u24_sSs:
432 sample_move_dither_rect_d32u24_sS;
433 break;
434
435 case Triangular:
436 printf("Triangular dithering at 16 bits\n");
437 write_via_copy = quirk_bswap?
438 sample_move_dither_tri_d32u24_sSs:
439 sample_move_dither_tri_d32u24_sS;
440 break;
441
442 case Shaped:
443 printf("Noise-shaped dithering at 32 bits\n");
444 write_via_copy = quirk_bswap?
445 sample_move_dither_shaped_d32u24_sSs:
446 sample_move_dither_shaped_d32u24_sS;
447 break;
448
449 default:
450 write_via_copy = quirk_bswap?
451 sample_move_d32u24_sSs : sample_move_d32u24_sS;
452 break;
453 }
454 break;
455 }
456
457 switch (capture_sample_bytes) {
458 case 2:
459 read_via_copy = quirk_bswap?
460 sample_move_dS_s16s : sample_move_dS_s16;
461 break;
462 case 3:
463 read_via_copy = quirk_bswap?
464 sample_move_dS_s24s : sample_move_dS_s24;
465 break;
466 case 4:
467 read_via_copy = quirk_bswap?
468 sample_move_dS_s32u24s : sample_move_dS_s32u24;
469 break;
470 }
471 }
472
configure_stream(char * device_name,const char * stream_name,snd_pcm_t * handle,snd_pcm_hw_params_t * hw_params,snd_pcm_sw_params_t * sw_params,unsigned int * nperiodsp,unsigned long * nchns,unsigned long sample_width)473 int AlsaDriver::configure_stream(char *device_name,
474 const char *stream_name,
475 snd_pcm_t *handle,
476 snd_pcm_hw_params_t *hw_params,
477 snd_pcm_sw_params_t *sw_params,
478 unsigned int *nperiodsp,
479 unsigned long *nchns,
480 unsigned long sample_width)
481 {
482 int err, format;
483 snd_pcm_uframes_t stop_th;
484 static struct {
485 char Name[32];
486 snd_pcm_format_t format;
487 int swapped;
488 int bitdepth;
489 } formats[] = {
490 {"32bit little-endian", SND_PCM_FORMAT_S32_LE, IS_LE, 32},
491 {"32bit big-endian", SND_PCM_FORMAT_S32_BE, IS_BE, 32},
492 {"24bit little-endian", SND_PCM_FORMAT_S24_3LE, IS_LE, 24},
493 {"24bit big-endian", SND_PCM_FORMAT_S24_3BE, IS_BE, 24},
494 {"16bit little-endian", SND_PCM_FORMAT_S16_LE, IS_LE, 16},
495 {"16bit big-endian", SND_PCM_FORMAT_S16_BE, IS_BE, 16},
496 };
497 #define NUMFORMATS (sizeof(formats)/sizeof(formats[0]))
498 #define FIRST_16BIT_FORMAT 4
499
500 if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {
501 printf("ALSA: no playback configurations available (%s)\n", snd_strerror (err));
502 return -1;
503 }
504
505 if ((err = snd_pcm_hw_params_set_periods_integer (handle, hw_params)) < 0) {
506 printf("ALSA: cannot restrict period size to integral value.\n");
507 return -1;
508 }
509
510 if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) < 0) {
511 if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) {
512 if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_MMAP_COMPLEX)) < 0) {
513 printf("ALSA: mmap-based access is not possible for the %s "
514 "stream of this audio interface\n", stream_name);
515 return -1;
516 }
517 }
518 }
519
520 format = (sample_width == 4) ? 0 : (NUMFORMATS - 1);
521 while (1) {
522 if ((err = snd_pcm_hw_params_set_format ( handle, hw_params, formats[format].format)) < 0) {
523
524 if (( (sample_width == 4) ? (format++ >= int(NUMFORMATS) - 1) : (format-- <= 0))) {
525 printf("ALSA Driver: Sorry. The audio interface \"%s\" doesn't support any of the"
526 " hardware sample formats that Traverso's alsa-driver can use.\n", device_name);
527 return -1;
528 }
529 } else {
530 if (formats[format].swapped) {
531 quirk_bswap = 1;
532 } else {
533 quirk_bswap = 0;
534 }
535 printf("ALSA: final selected sample format for %s: %s\n", stream_name, formats[format].Name);
536 device->set_bit_depth(formats[format].bitdepth);
537 break;
538 }
539 }
540
541 if ( (err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &frame_rate, NULL)) < 0) {
542 printf("ALSA: cannot set sample/frame rate to % for %s\n", (double)frame_rate, stream_name);
543 return -1;
544 }
545
546 if (!*nchns) {
547 /*if not user-specified, try to find the maximum number of channels */
548 unsigned int channels_max ;
549 err = snd_pcm_hw_params_get_channels_max (hw_params, &channels_max);
550 *nchns = channels_max;
551
552 if (*nchns > 1024) {
553
554 /* the hapless user is an unwitting victim of
555 the "default" ALSA PCM device, which can
556 support up to 16 million channels. since
557 they can't be bothered to set up a proper
558 default device, limit the number of
559 channels for them to a sane default.
560 */
561
562 PERROR (
563 "ALSA Driver: You appear to be using the ALSA software \"plug\" layer, probably\n"
564 "a result of using the \"default\" ALSA device. This is less\n"
565 "efficient than it could be. Consider using a hardware device\n"
566 "instead rather than using the plug layer. Usually the name of the\n"
567 "hardware device that corresponds to the first sound card is hw:0\n"
568 );
569 *nchns = 2;
570 }
571 }
572
573 if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, *nchns)) < 0) {
574 printf("ALSA: cannot set channel count to %lu for %s\n", *nchns, stream_name);
575 return -1;
576 }
577 int frperscycle = frames_per_cycle;
578 if ((err = snd_pcm_hw_params_set_period_size (handle, hw_params, frames_per_cycle, 0)) < 0) {
579 printf("ALSA: cannot set period size to %d frames for %s\n", frperscycle, stream_name);
580 return -1;
581 }
582
583 *nperiodsp = user_nperiods;
584 snd_pcm_hw_params_set_periods_min (handle, hw_params, nperiodsp, NULL);
585 if (*nperiodsp < user_nperiods)
586 *nperiodsp = user_nperiods;
587
588 if (snd_pcm_hw_params_set_periods_near (handle, hw_params, nperiodsp, NULL) < 0) {
589 printf("ALSA: cannot set number of periods to %u for %s\n", *nperiodsp, stream_name);
590 return -1;
591 }
592
593 if (*nperiodsp < user_nperiods) {
594 printf("ALSA: use %d periods for %s\n", *nperiodsp, stream_name);
595 return -1;
596 }
597
598 if (!is_power_of_two(frames_per_cycle)) {
599 printf("Traverso: frames must be a power of two (64, 512, 1024, ...)\n");
600 return -1;
601 }
602
603 if ((err = snd_pcm_hw_params_set_buffer_size (handle, hw_params, *nperiodsp * frames_per_cycle)) < 0) {
604 printf("ALSA: cannot set buffer length to %d for %s\n", *nperiodsp * frames_per_cycle, stream_name);
605 return -1;
606 }
607
608 if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) {
609 printf("ALSA: cannot set hardware parameters for %s\n", stream_name);
610 device->message(tr("ALSA Driver: Unable to configure hardware, is it in use by another application?"), AudioDevice::WARNING);
611 return -1;
612 }
613
614 snd_pcm_sw_params_current (handle, sw_params);
615
616 if ((err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, 0U)) < 0) {
617 printf("ALSA: cannot set start mode for %s\n", stream_name);
618 return -1;
619 }
620
621 stop_th = *nperiodsp * frames_per_cycle;
622 if (soft_mode) {
623 stop_th = (snd_pcm_uframes_t)-1;
624 }
625
626 if ((err = snd_pcm_sw_params_set_stop_threshold (handle, sw_params, stop_th)) < 0) {
627 printf("ALSA: cannot set stop mode for %s\n", stream_name);
628 return -1;
629 }
630
631 if ((err = snd_pcm_sw_params_set_silence_threshold (handle, sw_params, 0)) < 0) {
632 printf("ALSA: cannot set silence threshold for %s\n", stream_name);
633 return -1;
634 }
635
636 #if 0
637 fprintf (stderr, "set silence size to %lu * %lu = %lu\n",
638 frames_per_cycle, *nperiodsp,
639 frames_per_cycle * *nperiodsp);
640
641 if ((err = snd_pcm_sw_params_set_silence_size (
642 handle, sw_params,
643 frames_per_cycle * *nperiodsp)) < 0) {
644 PERROR ("ALSA: cannot set silence size for %s",
645 stream_name);
646 return -1;
647 }
648 #endif
649
650 if (handle == playback_handle)
651 err = snd_pcm_sw_params_set_avail_min (handle, sw_params, frames_per_cycle * (*nperiodsp - user_nperiods + 1));
652 else
653 err = snd_pcm_sw_params_set_avail_min (handle, sw_params, frames_per_cycle);
654
655 if (err < 0) {
656 printf("ALSA: cannot set avail min for %s\n", stream_name);
657 return -1;
658 }
659
660 if ((err = snd_pcm_sw_params (handle, sw_params)) < 0) {
661 printf("ALSA: cannot set software parameters for %s\n", stream_name);
662 return -1;
663 }
664
665 return 0;
666 }
667
set_parameters(nframes_t frames_per_interupt,nframes_t nperiods,nframes_t rate)668 int AlsaDriver::set_parameters (nframes_t frames_per_interupt,
669 nframes_t nperiods,
670 nframes_t rate)
671 {
672 int dir;
673 snd_pcm_uframes_t p_period_size = 0;
674 snd_pcm_uframes_t c_period_size = 0;
675 channel_t chn;
676 unsigned int pr = 0;
677 unsigned int cr = 0;
678 int err;
679
680 frame_rate = rate;
681 frames_per_cycle = frames_per_interupt;
682 user_nperiods = nperiods;
683
684 fprintf (stderr, "configuring for %d Hz, period=%ld frames (%.1f ms), buffer=%ld periods\n",
685 rate, (long)frames_per_cycle,(((float)frames_per_cycle / (float) rate) * 1000.0f), user_nperiods);
686 if (capture_handle) {
687 if (configure_stream (
688 alsa_name_capture,
689 "capture",
690 capture_handle,
691 capture_hw_params,
692 capture_sw_params,
693 &capture_nperiods,
694 &capture_nchannels,
695 capture_sample_bytes)) {
696 PERROR ("ALSA: cannot configure capture channel");
697 return -1;
698 }
699 }
700
701 if (playback_handle) {
702 if (configure_stream (
703 alsa_name_playback,
704 "playback",
705 playback_handle,
706 playback_hw_params,
707 playback_sw_params,
708 &playback_nperiods,
709 &playback_nchannels,
710 playback_sample_bytes)) {
711 PERROR ("ALSA: cannot configure playback channel");
712 return -1;
713 }
714 }
715
716 /* check the rate, since thats rather important */
717
718 if (playback_handle) {
719 snd_pcm_hw_params_get_rate (playback_hw_params, &pr, &dir);
720 }
721
722 if (capture_handle) {
723 snd_pcm_hw_params_get_rate (capture_hw_params, &cr, &dir);
724 }
725
726 if (capture_handle && playback_handle) {
727 if (cr != pr) {
728 PERROR ("ALSA Driver: playback and capture sample rates do not match (%d vs. %d)", pr, cr);
729 }
730
731 /* only change if *both* capture and playback rates
732 * don't match requested certain hardware actually
733 * still works properly in full-duplex with slightly
734 * different rate values between adc and dac
735 */
736 if (cr != frame_rate && pr != frame_rate) {
737 PERROR ("ALSA Driver: sample rate in use (%d Hz) does not match requested rate (%d Hz)", cr, frame_rate);
738 frame_rate = cr;
739 }
740
741 } else if (capture_handle && cr != frame_rate) {
742 PERROR ("ALSA Driver: capture sample rate in use (%d Hz) does not match requested rate (%d Hz)", cr, frame_rate);
743 frame_rate = cr;
744 } else if (playback_handle && pr != frame_rate) {
745 PERROR ("ALSA Driver: playback sample rate in use (%d Hz) does not match requested rate (%d Hz)", pr, frame_rate);
746 frame_rate = pr;
747 }
748
749
750 /* check the fragment size, since thats non-negotiable */
751
752 if (playback_handle) {
753 snd_pcm_access_t access;
754
755 err = snd_pcm_hw_params_get_period_size (playback_hw_params, &p_period_size, &dir);
756 err = snd_pcm_hw_params_get_format (playback_hw_params, &playback_sample_format);
757 err = snd_pcm_hw_params_get_access (playback_hw_params, &access);
758 playback_interleaved = (access == SND_PCM_ACCESS_MMAP_INTERLEAVED)
759 || (access == SND_PCM_ACCESS_MMAP_COMPLEX);
760
761 if (p_period_size != frames_per_cycle) {
762 PERROR ("alsa_pcm: requested an interrupt every %ld frames but got %ld frames for playback", (long)frames_per_cycle, p_period_size);
763 return -1;
764 }
765 }
766
767 if (capture_handle) {
768 snd_pcm_access_t access;
769
770 err = snd_pcm_hw_params_get_period_size (capture_hw_params, &c_period_size, &dir);
771 err = snd_pcm_hw_params_get_format (capture_hw_params, &(capture_sample_format));
772 err = snd_pcm_hw_params_get_access (capture_hw_params, &access);
773 capture_interleaved = (access == SND_PCM_ACCESS_MMAP_INTERLEAVED)
774 || (access == SND_PCM_ACCESS_MMAP_COMPLEX);
775
776
777 if (c_period_size != frames_per_cycle) {
778 PERROR ("alsa_pcm: requested an interrupt every %ld frames but got %ld frames for capture", (long)frames_per_cycle, p_period_size);
779 return -1;
780 }
781 }
782
783 playback_sample_bytes = snd_pcm_format_physical_width(playback_sample_format) / 8;
784 capture_sample_bytes = snd_pcm_format_physical_width(capture_sample_format) / 8;
785
786 if (playback_handle) {
787 switch (playback_sample_format) {
788 case SND_PCM_FORMAT_S32_LE:
789 case SND_PCM_FORMAT_S24_3LE:
790 case SND_PCM_FORMAT_S24_3BE:
791 case SND_PCM_FORMAT_S16_LE:
792 case SND_PCM_FORMAT_S32_BE:
793 case SND_PCM_FORMAT_S16_BE:
794 break;
795
796 default:
797 PERROR ("ALSA Driver: programming error: unhandled format type for playback");
798 return -1;
799 }
800 }
801
802 if (capture_handle) {
803 switch (capture_sample_format) {
804 case SND_PCM_FORMAT_S32_LE:
805 case SND_PCM_FORMAT_S24_3LE:
806 case SND_PCM_FORMAT_S24_3BE:
807 case SND_PCM_FORMAT_S16_LE:
808 case SND_PCM_FORMAT_S32_BE:
809 case SND_PCM_FORMAT_S16_BE:
810 break;
811
812 default:
813 PERROR ("ALSA Driver: programming error: unhandled format type for capture");
814 return -1;
815 }
816 }
817
818 if (playback_interleaved) {
819 const snd_pcm_channel_area_t *my_areas;
820 snd_pcm_uframes_t offset, frames;
821 if (snd_pcm_mmap_begin(playback_handle, &my_areas, &offset, &frames) < 0) {
822 PERROR ("ALSA: %s: mmap areas info error", alsa_name_playback);
823 return -1;
824 }
825
826 interleave_unit = snd_pcm_format_physical_width(playback_sample_format) / 8;
827 } else {
828 interleave_unit = 0; /* NOT USED */
829 }
830
831 if (capture_interleaved) {
832 const snd_pcm_channel_area_t *my_areas;
833 snd_pcm_uframes_t offset, frames;
834 if (snd_pcm_mmap_begin(capture_handle, &my_areas, &offset, &frames) < 0) {
835 PERROR ("ALSA: %s: mmap areas info error", alsa_name_capture);
836 return -1;
837 }
838 }
839
840 if (playback_nchannels > capture_nchannels) {
841 max_nchannels = playback_nchannels;
842 user_nchannels = capture_nchannels;
843 } else {
844 max_nchannels = capture_nchannels;
845 user_nchannels = playback_nchannels;
846 }
847
848 setup_io_function_pointers ();
849
850 /* Allocate and initialize structures that rely on the
851 channels counts.
852
853 Set up the bit pattern that is used to record which
854 channels require action on every cycle. any bits that are
855 not set after the engine's process() call indicate channels
856 that potentially need to be silenced.
857 */
858
859 bitset_create (&channels_done, max_nchannels);
860 bitset_create (&channels_not_done, max_nchannels);
861
862 if (playback_handle) {
863 playback_addr = (char**) malloc (sizeof (char *) * playback_nchannels);
864 memset (playback_addr, 0, sizeof (char *) * playback_nchannels);
865 playback_interleave_skip = (unsigned long *) malloc (sizeof (unsigned long *) * playback_nchannels);
866 memset (playback_interleave_skip, 0, sizeof (unsigned long *) * playback_nchannels);
867 silent = (unsigned long *) malloc (sizeof (unsigned long) * playback_nchannels);
868
869 for (chn = 0; chn < playback_nchannels; chn++) {
870 silent[chn] = 0;
871 }
872
873 for (chn = 0; chn < playback_nchannels; chn++) {
874 bitset_add (channels_done, chn);
875 }
876
877 dither_state = (dither_state_t *) calloc ( playback_nchannels, sizeof (dither_state_t));
878 }
879
880 if (capture_handle) {
881 capture_addr = (char **) malloc (sizeof (char *) * capture_nchannels);
882 memset (capture_addr, 0, sizeof (char *) * capture_nchannels);
883 capture_interleave_skip = (unsigned long *) malloc (sizeof (unsigned long *) * capture_nchannels);
884 memset (capture_interleave_skip, 0, sizeof (unsigned long *) * capture_nchannels);
885 }
886
887 period_usecs = (trav_time_t) floor ((((float) frames_per_cycle) / frame_rate) * 1000000.0f);
888 poll_timeout = (int) floor (1.5f * period_usecs);
889
890 device->set_buffer_size(frames_per_cycle);
891
892 return 0;
893 }
894
reset_parameters(nframes_t frames_per_cycle,nframes_t user_nperiods,nframes_t rate)895 int AlsaDriver::reset_parameters (nframes_t frames_per_cycle,
896 nframes_t user_nperiods,
897 nframes_t rate)
898 {
899 /* XXX unregister old ports ? */
900 release_channel_dependent_memory ();
901 return set_parameters (frames_per_cycle, user_nperiods, rate);
902 }
903
get_channel_addresses(snd_pcm_uframes_t * capture_avail,snd_pcm_uframes_t * playback_avail,snd_pcm_uframes_t * capture_offset,snd_pcm_uframes_t * playback_offset)904 int AlsaDriver::get_channel_addresses (snd_pcm_uframes_t *capture_avail,
905 snd_pcm_uframes_t *playback_avail,
906 snd_pcm_uframes_t *capture_offset,
907 snd_pcm_uframes_t *playback_offset)
908 {
909 int err;
910 channel_t chn;
911
912 if (capture_avail) {
913 if ((err = snd_pcm_mmap_begin (capture_handle, &capture_areas, capture_offset, capture_avail)) < 0) {
914 PERROR ("ALSA: %s: mmap areas info error", alsa_name_capture);
915 return -1;
916 }
917
918 for (chn = 0; chn < capture_nchannels; chn++) {
919 const snd_pcm_channel_area_t *a = &capture_areas[chn];
920 capture_addr[chn] = (char *) a->addr + ((a->first + a->step * *capture_offset) / 8);
921 capture_interleave_skip[chn] = (unsigned long ) (a->step / 8);
922 }
923 }
924
925 if (playback_avail) {
926 if ((err = snd_pcm_mmap_begin (playback_handle, &playback_areas, playback_offset, playback_avail)) < 0) {
927 PERROR ("ALSA: %s: mmap areas info error ", alsa_name_playback);
928 return -1;
929 }
930
931 for (chn = 0; chn < playback_nchannels; chn++) {
932 const snd_pcm_channel_area_t *a = &playback_areas[chn];
933 playback_addr[chn] = (char *) a->addr + ((a->first + a->step * *playback_offset) / 8);
934 playback_interleave_skip[chn] = (unsigned long ) (a->step / 8);
935 }
936 }
937
938 return 0;
939 }
940
start()941 int AlsaDriver::start()
942 {
943 int err;
944 snd_pcm_uframes_t poffset, pavail;
945 channel_t chn;
946
947 poll_last = 0;
948 poll_next = 0;
949
950 if (playback_handle) {
951 if ((err = snd_pcm_prepare (playback_handle)) < 0) {
952 PERROR ("ALSA: prepare error for playback on \"%s\" (%s)", alsa_name_playback, snd_strerror(err));
953 return -1;
954 }
955 }
956
957 if ((capture_handle && capture_and_playback_not_synced) || !playback_handle) {
958 if ((err = snd_pcm_prepare (capture_handle)) < 0) {
959 PERROR ("ALSA: prepare error for capture on \"%s\" (%s)", alsa_name_capture, snd_strerror(err));
960 return -1;
961 }
962 }
963
964
965 if (playback_handle) {
966 playback_nfds = snd_pcm_poll_descriptors_count (playback_handle);
967 } else {
968 playback_nfds = 0;
969 }
970
971 if (capture_handle) {
972 capture_nfds = snd_pcm_poll_descriptors_count (capture_handle);
973 } else {
974 capture_nfds = 0;
975 }
976
977 if (pfd) {
978 free (pfd);
979 }
980
981 pfd = (struct pollfd *) malloc (sizeof (struct pollfd) * (playback_nfds + capture_nfds + 2));
982
983 if (playback_handle) {
984 /* fill playback buffer with zeroes, and mark
985 all fragments as having data.
986 */
987
988 pavail = snd_pcm_avail_update (playback_handle);
989
990 if (pavail != frames_per_cycle * playback_nperiods) {
991 PERROR ("ALSA: full buffer not available at start");
992 return -1;
993 }
994
995 if (get_channel_addresses (0, &pavail, 0, &poffset)) {
996 return -1;
997 }
998
999 /* XXX this is cheating. ALSA offers no guarantee that
1000 we can access the entire buffer at any one time. It
1001 works on most hardware tested so far, however, buts
1002 its a liability in the long run. I think that
1003 alsa-lib may have a better function for doing this
1004 here, where the goal is to silence the entire
1005 buffer.
1006 */
1007
1008 for (chn = 0; chn < playback_nchannels; chn++) {
1009 silence_on_channel (chn, user_nperiods * frames_per_cycle);
1010 }
1011
1012 snd_pcm_mmap_commit (playback_handle, poffset, user_nperiods * frames_per_cycle);
1013
1014 if ((err = snd_pcm_start (playback_handle)) < 0) {
1015 PERROR ("ALSA: could not start playback (%s)", snd_strerror (err));
1016 return -1;
1017 }
1018 }
1019
1020 if ((capture_handle && capture_and_playback_not_synced) || !playback_handle) {
1021 if ((err = snd_pcm_start (capture_handle)) < 0) {
1022 PERROR ("ALSA: could not start capture (%s)", snd_strerror (err));
1023 return -1;
1024 }
1025 }
1026
1027 return 0;
1028 }
1029
stop()1030 int AlsaDriver::stop()
1031 {
1032 int err;
1033 audio_sample_t* buf;
1034
1035 /* silence all capture port buffers, because we might
1036 be entering offline mode.
1037 */
1038
1039 for (int i=0; i<captureChannels.size(); ++i) {
1040 AudioChannel* chan = captureChannels.at(i);
1041 buf = chan->get_buffer(frames_per_cycle);
1042 memset (buf, 0, sizeof (audio_sample_t) * frames_per_cycle);
1043 }
1044
1045 if (playback_handle) {
1046 if ((err = snd_pcm_drop (playback_handle)) < 0) {
1047 PERROR ("ALSA: channel flush for playback failed (%s)", snd_strerror (err));
1048 return -1;
1049 }
1050 }
1051
1052 if (!playback_handle || capture_and_playback_not_synced) {
1053 if (capture_handle) {
1054 if ((err = snd_pcm_drop (capture_handle)) < 0) {
1055 PERROR ("ALSA: channel flush for capture failed (%s)", snd_strerror (err));
1056 return -1;
1057 }
1058 }
1059 }
1060
1061
1062 return 0;
1063 }
1064
restart()1065 int AlsaDriver::restart()
1066 {
1067 if (stop())
1068 return -1;
1069 return start();
1070 }
1071
xrun_recovery(float * delayed_usecs)1072 int AlsaDriver::xrun_recovery (float *delayed_usecs)
1073 {
1074 PWARN("xrun");
1075 snd_pcm_status_t *status;
1076 int res;
1077
1078 snd_pcm_status_alloca(&status);
1079
1080 if (capture_handle) {
1081 if ((res = snd_pcm_status(capture_handle, status)) < 0) {
1082 printf ("status error: %s", snd_strerror(res));
1083 }
1084 } else {
1085 if ((res = snd_pcm_status(playback_handle, status)) < 0) {
1086 printf ("status error: %s", snd_strerror(res));
1087 }
1088 }
1089
1090 if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN && process_count > XRUN_REPORT_DELAY) {
1091 struct timeval now, diff, tstamp;
1092 gettimeofday(&now, 0);
1093 snd_pcm_status_get_trigger_tstamp(status, &tstamp);
1094 timersub(&now, &tstamp, &diff);
1095 *delayed_usecs = diff.tv_sec * 1000000.0 + diff.tv_usec;
1096 printf ("\n**** alsa_pcm: xrun of at least %.3f msecs\n\n", *delayed_usecs / 1000.0);
1097 device->xrun();
1098 }
1099
1100 if (restart()) {
1101 return -1;
1102 }
1103
1104 return 0;
1105 }
1106
silence_untouched_channels(nframes_t nframes)1107 void AlsaDriver::silence_untouched_channels (nframes_t nframes)
1108 {
1109 channel_t chn;
1110 nframes_t buffer_frames = frames_per_cycle * playback_nperiods;
1111
1112 for (chn = 0; chn < playback_nchannels; chn++) {
1113 if (bitset_contains (channels_not_done, chn)) {
1114 if (silent[chn] < buffer_frames) {
1115 silence_on_channel_no_mark (chn, nframes);
1116 silent[chn] += nframes;
1117 }
1118 }
1119 }
1120 }
1121
1122 static int under_gdb = false;
1123
wait(int extra_fd,int * status,float * delayed_usecs)1124 int AlsaDriver::wait(int extra_fd, int *status, float *delayed_usecs)
1125 {
1126 snd_pcm_sframes_t avail = 0;
1127 snd_pcm_sframes_t capture_avail = 0;
1128 snd_pcm_sframes_t playback_avail = 0;
1129 int xrun_detected = false;
1130 int need_capture;
1131 int need_playback;
1132 unsigned int i;
1133 trav_time_t poll_enter;
1134 trav_time_t poll_ret = 0;
1135
1136 *status = -1;
1137 *delayed_usecs = 0;
1138
1139 need_capture = capture_handle ? 1 : 0;
1140
1141 if (extra_fd >= 0) {
1142 need_playback = 0;
1143 } else {
1144 need_playback = playback_handle ? 1 : 0;
1145 }
1146
1147 again:
1148
1149 while (need_playback || need_capture) {
1150
1151 int poll_result;
1152 unsigned int ci = 0;
1153 unsigned int nfds;
1154 unsigned short revents;
1155
1156 nfds = 0;
1157
1158 if (need_playback) {
1159 snd_pcm_poll_descriptors (playback_handle, &pfd[0], playback_nfds);
1160 nfds += playback_nfds;
1161 }
1162
1163 if (need_capture) {
1164 snd_pcm_poll_descriptors (capture_handle, &pfd[nfds], capture_nfds);
1165 ci = nfds;
1166 nfds += capture_nfds;
1167 }
1168
1169 /* ALSA doesn't set POLLERR in some versions of 0.9.X */
1170
1171 for (i = 0; i < nfds; i++) {
1172 pfd[i].events |= POLLERR;
1173 }
1174
1175 if (extra_fd >= 0) {
1176 pfd[nfds].fd = extra_fd;
1177 pfd[nfds].events =
1178 POLLIN|POLLERR|POLLHUP|POLLNVAL;
1179 nfds++;
1180 }
1181
1182 poll_enter = get_microseconds ();
1183
1184 if (poll_enter > poll_next) {
1185 /*
1186 * This processing cycle was delayed past the
1187 * next due interrupt! Do not account this as
1188 * a wakeup delay:
1189 */
1190 poll_next = 0;
1191 }
1192
1193 device->transport_cycle_end(poll_enter);
1194
1195 poll_result = poll (pfd, nfds, poll_timeout);
1196 if (poll_result < 0) {
1197
1198 if (errno == EINTR) {
1199 printf ("poll interrupt\n");
1200 // this happens mostly when run
1201 // under gdb, or when exiting due to a signal
1202 if (under_gdb) {
1203 goto again;
1204 }
1205 *status = -2;
1206 return 0;
1207 }
1208
1209 PERROR ("ALSA: poll call failed (%s)",
1210 strerror (errno));
1211 *status = -3;
1212 return 0;
1213
1214 }
1215
1216 poll_ret = get_microseconds ();
1217
1218 if (extra_fd < 0) {
1219 if (poll_next && poll_ret > poll_next) {
1220 *delayed_usecs = poll_ret - poll_next;
1221 }
1222 poll_last = poll_ret;
1223 poll_next = poll_ret + period_usecs;
1224 device->transport_cycle_start (poll_ret);
1225 }
1226
1227 #ifdef DEBUG_WAKEUP
1228 fprintf (stderr, "%" PRIu64 ": checked %d fds, %" PRIu64
1229 " usecs since poll entered\n", poll_ret, nfds,
1230 poll_ret - poll_enter);
1231 #endif
1232
1233 /* check to see if it was the extra FD that caused us
1234 * to return from poll */
1235
1236 if (extra_fd >= 0) {
1237
1238 if (pfd[nfds-1].revents == 0) {
1239 /* we timed out on the extra fd */
1240
1241 *status = -4;
1242 return -1;
1243 }
1244
1245 /* if POLLIN was the only bit set, we're OK */
1246
1247 *status = 0;
1248 return (pfd[nfds-1].revents == POLLIN) ? 0 : -1;
1249 }
1250
1251 if (need_playback) {
1252 if (snd_pcm_poll_descriptors_revents(playback_handle, &pfd[0], playback_nfds, &revents) < 0) {
1253 qWarning("ALSA: playback revents failed");
1254 *status = -6;
1255 return 0;
1256 }
1257
1258 if (revents & POLLERR) {
1259 xrun_detected = true;
1260 }
1261
1262 if (revents & POLLOUT) {
1263 need_playback = 0;
1264
1265 #ifdef DEBUG_WAKEUP
1266
1267 fprintf (stderr, "%" PRIu64
1268 " playback stream ready\n",
1269 poll_ret);
1270 #endif
1271
1272 }
1273 }
1274
1275 if (need_capture) {
1276 if (snd_pcm_poll_descriptors_revents(capture_handle, &pfd[ci], capture_nfds, &revents) < 0) {
1277 qWarning ("ALSA: capture revents failed");
1278 *status = -6;
1279 return 0;
1280 }
1281
1282 if (revents & POLLERR) {
1283 xrun_detected = true;
1284 }
1285
1286 if (revents & POLLIN) {
1287 need_capture = 0;
1288 #ifdef DEBUG_WAKEUP
1289
1290 fprintf (stderr, "%" PRIu64
1291 " capture stream ready\n",
1292 poll_ret);
1293 #endif
1294
1295 }
1296 }
1297
1298 if (poll_result == 0) {
1299 qWarning ("ALSA: poll time out, polled for %ld usecs", (long)(poll_ret - poll_enter));
1300 *status = -5;
1301 return 0;
1302 }
1303
1304 }
1305
1306 if (capture_handle) {
1307 if ((capture_avail = snd_pcm_avail_update (capture_handle)) < 0) {
1308 if (capture_avail == -EPIPE) {
1309 xrun_detected = true;
1310 } else {
1311 PERROR ("ALSA Driver: unknown avail_update return value (%ld)", capture_avail);
1312 }
1313 }
1314 } else {
1315 /* odd, but see min() computation below */
1316 capture_avail = INT_MAX;
1317 }
1318
1319 if (playback_handle) {
1320 if ((playback_avail = snd_pcm_avail_update (playback_handle)) < 0) {
1321 if (playback_avail == -EPIPE) {
1322 xrun_detected = true;
1323 } else {
1324 PERROR ("ALSA Driver: unknown avail_update return value (%ld)", playback_avail);
1325 }
1326 }
1327 } else {
1328 /* odd, but see min() computation below */
1329 playback_avail = INT_MAX;
1330 }
1331
1332 if (xrun_detected) {
1333 *status = xrun_recovery (delayed_usecs);
1334 return 0;
1335 }
1336
1337 *status = 0;
1338 last_wait_ust = poll_ret;
1339
1340 avail = capture_avail < playback_avail ? capture_avail : playback_avail;
1341
1342 #ifdef DEBUG_WAKEUP
1343
1344 fprintf (stderr, "wakeup complete, avail = %lu, pavail = %lu "
1345 "cavail = %lu\n",
1346 avail, playback_avail, capture_avail);
1347 #endif
1348
1349 /* mark all channels not done for now. read/write will change this */
1350
1351 bitset_copy (channels_not_done, channels_done);
1352
1353 /* constrain the available count to the nearest (round down) number of
1354 periods.
1355 */
1356
1357 return avail - (avail % frames_per_cycle);
1358 }
1359
_null_cycle(nframes_t nframes)1360 int AlsaDriver::_null_cycle(nframes_t nframes)
1361 {
1362 nframes_t nf;
1363 snd_pcm_uframes_t offset;
1364 snd_pcm_uframes_t contiguous;
1365 uint chn;
1366
1367 if (nframes > frames_per_cycle) {
1368 return -1;
1369 }
1370
1371 if (capture_handle) {
1372 nf = nframes;
1373 offset = 0;
1374 while (nf) {
1375 contiguous = nf;
1376
1377 if (snd_pcm_mmap_begin (
1378 capture_handle,
1379 &capture_areas,
1380 (snd_pcm_uframes_t *) &offset,
1381 (snd_pcm_uframes_t *) &contiguous)) {
1382 return -1;
1383 }
1384
1385 if (snd_pcm_mmap_commit (capture_handle, offset, contiguous) < 0) {
1386 return -1;
1387 }
1388
1389 nf -= contiguous;
1390 }
1391 }
1392
1393 if (playback_handle) {
1394 nf = nframes;
1395 offset = 0;
1396 while (nf) {
1397 contiguous = nf;
1398
1399 if (snd_pcm_mmap_begin (
1400 playback_handle,
1401 &playback_areas,
1402 (snd_pcm_uframes_t *) &offset,
1403 (snd_pcm_uframes_t *) &contiguous)) {
1404 return -1;
1405 }
1406
1407 for (chn = 0; chn < playback_nchannels; chn++) {
1408 silence_on_channel (chn, contiguous);
1409 }
1410
1411 if (snd_pcm_mmap_commit (playback_handle, offset, contiguous) < 0) {
1412 return -1;
1413 }
1414
1415 nf -= contiguous;
1416 }
1417 }
1418
1419 return 0;
1420 }
1421
bufsize(nframes_t nframes)1422 int AlsaDriver::bufsize(nframes_t nframes)
1423 {
1424 return reset_parameters (nframes, user_nperiods,frame_rate);
1425 }
1426
_read(nframes_t nframes)1427 int AlsaDriver::_read(nframes_t nframes)
1428 {
1429 snd_pcm_uframes_t contiguous;
1430 snd_pcm_uframes_t nread;
1431 snd_pcm_uframes_t offset;
1432 nframes_t orig_nframes;
1433 audio_sample_t* buf;
1434 int err;
1435
1436 if (nframes > frames_per_cycle) {
1437 return -1;
1438 }
1439
1440 if (!capture_handle) {
1441 return 0;
1442 }
1443
1444 nread = 0;
1445 contiguous = 0;
1446 orig_nframes = nframes;
1447
1448 while (nframes) {
1449
1450 contiguous = nframes;
1451
1452 if (get_channel_addresses (&contiguous, (snd_pcm_uframes_t *) 0, &offset, 0) < 0) {
1453 return -1;
1454 }
1455
1456 for (int i=0; i<captureChannels.size(); ++i) {
1457 AudioChannel* channel = captureChannels.at(i);
1458
1459 if (!channel->has_data()) {
1460 //no-copy optimization
1461 continue;
1462 }
1463 buf = channel->get_data();
1464 read_from_channel (channel->get_number(), buf + nread, contiguous);
1465 }
1466
1467 if ((err = snd_pcm_mmap_commit (capture_handle, offset, contiguous)) < 0) {
1468 PERROR ("ALSA: could not complete read of %ld frames: error = %d\n", contiguous, err);
1469 return -1;
1470 }
1471
1472 nframes -= contiguous;
1473 nread += contiguous;
1474 }
1475
1476 return 0;
1477 }
1478
_write(nframes_t nframes)1479 int AlsaDriver::_write(nframes_t nframes)
1480 {
1481 audio_sample_t* buf;
1482 nframes_t orig_nframes;
1483 snd_pcm_uframes_t nwritten;
1484 snd_pcm_uframes_t contiguous;
1485 snd_pcm_uframes_t offset;
1486 int err;
1487
1488 process_count++;
1489
1490 if (! playback_handle) {
1491 return 0;
1492 }
1493
1494 if (nframes > frames_per_cycle) {
1495 return -1;
1496 }
1497
1498 nwritten = 0;
1499 contiguous = 0;
1500 orig_nframes = nframes;
1501
1502 while (nframes) {
1503
1504 contiguous = nframes;
1505
1506 if (get_channel_addresses ((snd_pcm_uframes_t *) 0, &contiguous, 0, &offset) < 0) {
1507 return -1;
1508 }
1509
1510 for (int i=0; i<playbackChannels.size(); ++i) {
1511 AudioChannel* channel = playbackChannels.at(i);
1512 if (!channel->has_data()) {
1513 continue;
1514 }
1515 buf = channel->get_data();
1516 write_to_channel (channel->get_number(), buf + nwritten, contiguous);
1517 channel->silence_buffer(nframes);
1518 }
1519
1520
1521 if (!bitset_empty (channels_not_done)) {
1522 silence_untouched_channels (contiguous);
1523 }
1524
1525 if ((err = snd_pcm_mmap_commit (playback_handle, offset, contiguous)) < 0) {
1526 PERROR ("ALSA: could not complete playback of %ld frames: error = %d", contiguous, err);
1527 if (err != EPIPE && err != ESTRPIPE)
1528 return -1;
1529 }
1530
1531 nframes -= contiguous;
1532 nwritten += contiguous;
1533 }
1534 return 0;
1535 }
1536
_run_cycle()1537 int AlsaDriver::_run_cycle()
1538 {
1539 int wait_status;
1540 float delayed_usecs;
1541 nframes_t nframes;
1542
1543 // PWARN ("alsa run cycle wait\n");
1544
1545 nframes = wait (-1, &wait_status, &delayed_usecs);
1546
1547
1548 if (nframes == 0) {
1549
1550 /* we detected an xrun and restarted: notify
1551 * clients about the delay.
1552 */
1553 device->delay(delayed_usecs);
1554 return 0;
1555 }
1556
1557 if (wait_status == 0)
1558 return device->run_cycle (nframes, delayed_usecs);
1559
1560 if (wait_status < 0)
1561 return -1; /* driver failed */
1562 else
1563 return 0;
1564 }
1565
attach()1566 int AlsaDriver::attach()
1567 {
1568 char buf[32];
1569 channel_t chn;
1570 AudioChannel* chan;
1571 int port_flags;
1572
1573 device->set_buffer_size (frames_per_cycle);
1574 device->set_sample_rate (frame_rate);
1575
1576 port_flags = PortIsOutput|PortIsPhysical|PortIsTerminal;
1577
1578 for (chn = 0; chn < capture_nchannels; chn++) {
1579
1580 snprintf (buf, sizeof(buf) - 1, "capture_%lu", chn+1);
1581
1582 chan = device->register_capture_channel(buf, "32 bit float audio", port_flags, frames_per_cycle, chn);
1583 chan->set_latency( frames_per_cycle + capture_frame_latency );
1584 captureChannels.append(chan);
1585
1586 }
1587
1588 port_flags = PortIsInput|PortIsPhysical|PortIsTerminal;
1589
1590 for (chn = 0; chn < playback_nchannels; chn++) {
1591
1592 snprintf (buf, sizeof(buf) - 1, "playback_%lu", chn+1);
1593
1594 chan = device->register_playback_channel(buf, "32 bit float audio", port_flags, frames_per_cycle, chn);
1595 chan->set_latency( frames_per_cycle + capture_frame_latency );
1596 playbackChannels.append(chan);
1597 }
1598
1599
1600 return 1;
1601 }
1602
detach()1603 int AlsaDriver::detach ()
1604 {
1605 return 0;
1606 }
1607
get_device_name()1608 QString AlsaDriver::get_device_name( )
1609 {
1610 return alsa_device_name(false);
1611 }
1612
get_device_longname()1613 QString AlsaDriver::get_device_longname( )
1614 {
1615 return alsa_device_name(true);
1616 }
1617
alsa_device_name(bool longname,int devicenumber)1618 QString AlsaDriver::alsa_device_name(bool longname, int devicenumber)
1619 {
1620 snd_ctl_card_info_t *info;
1621 snd_ctl_t *handle;
1622 char name[32];
1623 sprintf(name, "hw:%d", devicenumber);
1624 int err = 0;
1625
1626 snd_ctl_card_info_alloca(&info);
1627
1628 if ((err = snd_ctl_open(&handle, name, devicenumber)) < 0) {
1629 PMESG("AlsaDriver::alsa_device_name: Control open (device %i): %s", devicenumber, snd_strerror(err));
1630 return "";
1631 }
1632
1633 if ((err = snd_ctl_card_info(handle, info)) < 0) {
1634 PMESG("Control hardware info (%i): %s", 0, snd_strerror(err));
1635 }
1636
1637 snd_ctl_close(handle);
1638
1639 if (err < 0) {
1640 return "Device name unknown";
1641 }
1642
1643
1644 if (longname) {
1645 return snd_ctl_card_info_get_name(info);
1646 }
1647
1648 return snd_ctl_card_info_get_id(info);
1649 }
1650
1651 //eof
1652