4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "audiodevice.h"
24 #include "audioalsa.h"
25 #include "bcsignals.h"
28 #include "playbackconfig.h"
29 #include "preferences.h"
30 #include "recordconfig.h"
36 AudioALSA::AudioALSA(AudioDevice *device)
37 : AudioLowLevel(device)
44 timer_lock = new Mutex("AudioALSA::timer_lock");
50 AudioALSA::~AudioALSA()
57 static class alsa_leaks
60 // This is required in the top thread for Alsa to work
62 ArrayList<char*> *alsa_titles = new ArrayList<char*>;
63 alsa_titles->set_array_delete();
64 AudioALSA::list_devices(alsa_titles, 0, MODEPLAY);
65 alsa_titles->remove_all_objects();
68 ~alsa_leaks() { snd_config_update_free_global(); }
71 void AudioALSA::list_devices(ArrayList<char*> *names, ArrayList<char*> *pcm_names, int mode)
75 snd_ctl_card_info_t *info;
76 snd_pcm_info_t *pcminfo;
77 char string[BCTEXTLEN];
78 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
83 stream = SND_PCM_STREAM_CAPTURE;
86 stream = SND_PCM_STREAM_PLAYBACK;
91 snd_ctl_card_info_alloca(&info);
92 snd_pcm_info_alloca(&pcminfo);
95 #define DEFAULT_DEVICE "default"
97 names->append(cstrdup(DEFAULT_DEVICE));
99 pcm_names->append(cstrdup(DEFAULT_DEVICE));
101 while(snd_card_next(&card) >= 0) {
102 char name[BCTEXTLEN];
104 sprintf(name, "hw:%i", card);
106 if((err = snd_ctl_open(&handle, name, 0)) < 0) {
107 printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err));
111 if((err = snd_ctl_card_info(handle, info)) < 0) {
112 printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err));
113 snd_ctl_close(handle);
120 if(snd_ctl_pcm_next_device(handle, &dev) < 0)
121 printf("AudioALSA::list_devices: snd_ctl_pcm_next_device\n");
125 snd_pcm_info_set_device(pcminfo, dev);
126 snd_pcm_info_set_subdevice(pcminfo, 0);
127 snd_pcm_info_set_stream(pcminfo, stream);
129 if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
131 printf("AudioALSA::list_devices card=%i: %s\n", card, snd_strerror(err));
136 sprintf(string, "plughw:%d,%d", card, dev);
137 // strcpy(string, "cards.pcm.front");
138 pcm_names->append(cstrdup(string));
141 sprintf(string, "%s #%d",
142 snd_ctl_card_info_get_name(info), dev);
143 names->append(cstrdup(string));
147 snd_ctl_close(handle);
151 void AudioALSA::translate_name(char *output, char *input, int mode)
153 ArrayList<char*> titles;
154 titles.set_array_delete();
156 ArrayList<char*> pcm_titles;
157 pcm_titles.set_array_delete();
159 list_devices(&titles, &pcm_titles, mode);
161 // attempt to add pulseaudio "monitor" devices
162 add_pulse_devices(mode, &titles, &pcm_titles);
164 sprintf(output, "default");
165 for(int i = 0; i < titles.total; i++)
167 //printf("AudioALSA::translate_name %s %s\n", titles.values[i], pcm_titles.values[i]);
168 if(!strcasecmp(titles.values[i], input))
170 strcpy(output, pcm_titles.values[i]);
175 titles.remove_all_objects();
176 pcm_titles.remove_all_objects();
179 snd_pcm_format_t AudioALSA::translate_format(int format)
183 case 8: return SND_PCM_FORMAT_S8;
184 case 16: return SND_PCM_FORMAT_S16_LE;
185 case 24: return SND_PCM_FORMAT_S24_LE;
186 case 32: return SND_PCM_FORMAT_S32_LE;
188 return SND_PCM_FORMAT_UNKNOWN;
191 int AudioALSA::set_params(snd_pcm_t *dsp, int mode,
192 int channels, int bits, int samplerate, int samples)
194 snd_pcm_hw_params_t *params;
195 snd_pcm_sw_params_t *swparams;
198 snd_pcm_hw_params_alloca(¶ms);
199 snd_pcm_sw_params_alloca(&swparams);
200 err = snd_pcm_hw_params_any(dsp, params);
203 fprintf(stderr, "AudioALSA::set_params: ");
204 fprintf(stderr, _("no PCM configurations available\n"));
208 err=snd_pcm_hw_params_set_access(dsp,
210 SND_PCM_ACCESS_RW_INTERLEAVED);
212 fprintf(stderr, "AudioALSA::set_params: ");
213 fprintf(stderr, _("failed to set up interleaved device access.\n"));
217 err=snd_pcm_hw_params_set_format(dsp,
219 translate_format(bits));
221 fprintf(stderr, "AudioALSA::set_params: ");
222 fprintf(stderr, _("failed to set output format.\n"));
226 err=snd_pcm_hw_params_set_channels(dsp,
230 fprintf(stderr, "AudioALSA::set_params: ");
231 fprintf(stderr, _("Configured ALSA device does not support %d channel operation.\n"),
236 err=snd_pcm_hw_params_set_rate_near(dsp,
238 (unsigned int*)&samplerate,
241 fprintf(stderr, "AudioALSA::set_params: ");
242 fprintf(stderr, _(" Configured ALSA device does not support %u Hz playback.\n"),
243 (unsigned int)samplerate);
247 // Buffers written must be equal to period_time
249 int period_time = (int)(1000000 * (double)samples / samplerate);
252 buffer_time = 10000000;
255 buffer_time = 2 * period_time;
259 //printf("AudioALSA::set_params 1 %d %d %d\n", samples, buffer_time, period_time);
260 snd_pcm_hw_params_set_buffer_time_near(dsp,
262 (unsigned int*)&buffer_time,
264 snd_pcm_hw_params_set_period_time_near(dsp,
266 (unsigned int*)&period_time,
268 //printf("AudioALSA::set_params 5 %d %d\n", buffer_time, period_time);
269 err = snd_pcm_hw_params(dsp, params);
271 fprintf(stderr, "AudioALSA::set_params: hw_params failed\n");
275 snd_pcm_uframes_t chunk_size = 1024;
276 snd_pcm_uframes_t buffer_size = 262144;
277 snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
278 snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
279 //printf("AudioALSA::set_params 10 %d %d\n", chunk_size, buffer_size);
281 snd_pcm_sw_params_current(dsp, swparams);
282 //snd_pcm_uframes_t xfer_align = 1;
283 //snd_pcm_sw_params_get_xfer_align(swparams, &xfer_align);
284 //unsigned int sleep_min = 0;
285 //err = snd_pcm_sw_params_set_sleep_min(dsp, swparams, sleep_min);
286 period_size = chunk_size;
287 err = snd_pcm_sw_params_set_avail_min(dsp, swparams, period_size);
288 //err = snd_pcm_sw_params_set_xfer_align(dsp, swparams, xfer_align);
289 if(snd_pcm_sw_params(dsp, swparams) < 0) {
290 /* we can continue staggering along even if this fails */
291 fprintf(stderr, "AudioALSA::set_params: snd_pcm_sw_params failed\n");
294 device->device_buffer = samples * bits / 8 * channels;
296 //printf("AudioALSA::set_params 100 %d %d\n", samples, device->device_buffer);
298 // snd_pcm_hw_params_free(params);
299 // snd_pcm_sw_params_free(swparams);
303 int AudioALSA::open_input()
305 char pcm_name[BCTEXTLEN];
306 snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
310 device->in_channels = device->get_ichannels();
311 device->in_bits = device->in_config->alsa_in_bits;
313 translate_name(pcm_name, device->in_config->alsa_in_device,MODERECORD);
314 //printf("AudioALSA::open_input %s\n", pcm_name);
316 err = snd_pcm_open(&dsp_in, pcm_name, stream, open_mode);
320 printf("AudioALSA::open_input: %s\n", snd_strerror(err));
324 err = set_params(dsp_in, MODERECORD,
325 device->get_ichannels(),
326 device->in_config->alsa_in_bits,
327 device->in_samplerate,
330 fprintf(stderr, "AudioALSA::open_input: set_params failed. Aborting sampling.\n");
338 int AudioALSA::open_output()
340 char pcm_name[BCTEXTLEN];
341 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
342 int open_mode = SND_PCM_NONBLOCK;
345 device->out_channels = device->get_ochannels();
346 device->out_bits = device->out_config->alsa_out_bits;
348 //printf("AudioALSA::open_output out_device %s\n", device->out_config->alsa_out_device);
349 translate_name(pcm_name, device->out_config->alsa_out_device,MODEPLAY);
350 //printf("AudioALSA::open_output pcm_name %s\n", pcm_name);
352 err = snd_pcm_open(&dsp_out, pcm_name, stream, open_mode);
357 printf("AudioALSA::open_output %s: %s\n", pcm_name, snd_strerror(err));
361 err = set_params(dsp_out, MODEPLAY,
362 device->get_ochannels(),
363 device->out_config->alsa_out_bits,
364 device->out_samplerate,
365 device->out_samples);
367 fprintf(stderr, "AudioALSA::open_output: set_params failed. Aborting playback.\n");
376 int AudioALSA::stop_output()
378 //printf("AudioALSA::stop_output\n");
379 if(!device->out_config->interrupt_workaround)
382 snd_pcm_drop(get_output());
389 int AudioALSA::close_output()
391 //printf("AudioALSA::close_output\n");
392 if(device->w && dsp_out) {
394 snd_pcm_close(dsp_out);
400 int AudioALSA::close_input()
402 //printf("AudioALSA::close_input\n");
403 if(device->r && dsp_in) {
404 // snd_pcm_reset(dsp_in);
405 snd_pcm_drop(dsp_in);
406 snd_pcm_drain(dsp_in);
407 snd_pcm_close(dsp_in);
413 int AudioALSA::close_all()
415 //printf("AudioALSA::close_all\n");
426 int64_t AudioALSA::device_position()
428 timer_lock->lock("AudioALSA::device_position");
429 int64_t delta = timer->get_scaled_difference(device->out_samplerate);
430 int64_t result = buffer_position - delay + delta;
431 //printf("AudioALSA::device_position 1 w=%jd dt=%jd dly=%d pos=%jd\n",
432 // buffer_position, delta, delay, result);
433 timer_lock->unlock();
437 int AudioALSA::read_buffer(char *buffer, int size)
439 //printf("AudioALSA::read_buffer 1\n");
442 int frame_size = (device->in_bits / 8) * device->get_ichannels();
451 while(attempts < 1 && !done)
453 snd_pcm_uframes_t frames = size / frame_size;
454 result = snd_pcm_readi(get_input(), buffer, frames);
457 printf("AudioALSA::read_buffer overrun at sample %jd\n",
458 device->total_samples_read);
459 // snd_pcm_resume(get_input());
460 close_input(); open_input();
465 //printf("AudioALSA::read_buffer %d result=%d done=%d\n", __LINE__, result, done);
470 int AudioALSA::write_buffer(char *buffer, int size)
472 //printf("AudioALSA::write_buffer %d\n",size);
473 // Don't give up and drop the buffer on the first error.
476 int sample_size = (device->out_bits / 8) * device->get_ochannels();
477 int samples = size / sample_size;
478 //printf("AudioALSA::write_buffer %d\n",samples);
480 snd_pcm_sframes_t delay = 0;
482 // static FILE *debug_fd = 0;
485 // debug_fd = fopen("/tmp/debug.pcm", "w");
487 // fwrite(buffer, size, 1, debug_fd);
491 if(!get_output()) return 0;
492 if( buffer_position == 0 )
495 AudioThread *audio_out = device->audio_out;
496 while( count > 0 && attempts < 2 && !done ) {
497 if( device->playback_interrupted ) break;
498 // Buffers written must be equal to period_time
499 audio_out->Thread::enable_cancel();
500 int ret = snd_pcm_avail_update(get_output());
501 if( ret >= period_size ) {
502 if( ret > count ) ret = count;
504 //if( !alsa_fp ) alsa_fp = fopen("/tmp/alsa.raw","w");
505 //if( alsa_fp ) fwrite(buffer, sample_size, ret, alsa_fp);
506 //printf("AudioALSA::snd_pcm_writei start %d\n",count);
507 ret = snd_pcm_writei(get_output(),buffer,ret);
508 //printf("AudioALSA::snd_pcm_writei done %d\n", ret);
510 else if( ret >= 0 || ret == -EAGAIN ) {
511 ret = snd_pcm_wait(get_output(),15);
512 if( ret > 0 ) ret = 0;
514 audio_out->Thread::disable_cancel();
515 if( device->playback_interrupted ) break;
516 if( ret == 0 ) continue;
519 samples_written += ret;
520 if( (count-=ret) > 0 ) {
521 buffer += ret * sample_size;
528 printf(_("AudioALSA::write_buffer err %d(%s) at sample %jd\n"),
529 ret, snd_strerror(ret), device->current_position());
531 // snd_pcm_resume(get_output());
532 snd_pcm_recover(get_output(), ret, 1);
533 // close_output(); open_output();
538 if( !interrupted && device->playback_interrupted )
541 //printf("AudioALSA::write_buffer interrupted\n");
547 timer_lock->lock("AudioALSA::write_buffer");
548 snd_pcm_delay(get_output(), &delay);
551 buffer_position += samples;
552 //printf("AudioALSA::write_buffer ** wrote %d, delay %d\n",samples,(int)delay);
553 timer_lock->unlock();
558 //this delay seems to prevent a problem where the sound system outputs
559 //a lot of silence while waiting for the device drain to happen.
560 int AudioALSA::output_wait()
562 snd_pcm_sframes_t delay = 0;
563 snd_pcm_delay(get_output(), &delay);
564 if( delay <= 0 ) return 0;
565 int64_t udelay = 1e6 * delay / device->out_samplerate;
566 // don't allow more than 10 seconds
567 if( udelay > 10000000 ) udelay = 10000000;
568 while( udelay > 0 && !device->playback_interrupted ) {
569 int64_t usecs = udelay;
570 if( usecs > 100000 ) usecs = 100000;
574 if( device->playback_interrupted &&
575 !device->out_config->interrupt_workaround )
576 snd_pcm_drop(get_output());
580 int AudioALSA::flush_device()
582 //printf("AudioALSA::flush_device\n");
586 //this causes the output to stutter.
587 //snd_pcm_nonblock(get_output(), 0);
588 snd_pcm_drain(get_output());
589 //snd_pcm_nonblock(get_output(), 1);
594 int AudioALSA::interrupt_playback()
596 //printf("AudioALSA::interrupt_playback *********\n");
599 // Interrupts the playback but may not have caused snd_pcm_writei to exit.
600 // With some soundcards it causes snd_pcm_writei to freeze for a few seconds.
601 // if(!device->out_config->interrupt_workaround)
602 // snd_pcm_drop(get_output());
604 // Makes sure the current buffer finishes before stopping.
605 // snd_pcm_drain(get_output());
607 // The only way to ensure snd_pcm_writei exits, but
608 // got a lot of crashes when doing this.
609 // device->Thread::cancel();
615 snd_pcm_t* AudioALSA::get_output()
620 snd_pcm_t* AudioALSA::get_input()
625 void AudioALSA::add_pulse_devices(int mode,
626 ArrayList<char*> *names, ArrayList<char*> *pcm_names)
629 // run: pactl list <sources>|<sinks>
630 // scan output for <Source/Sink> #n, Name: <device>
631 // build alsa device config and add to alsa snd_config
642 char line[BCTEXTLEN];
644 sprintf(line, "LANGUAGE=en_US.UTF-8 pactl list %ss", arg);
645 pactl = popen(line,"r");
649 char name[BCTEXTLEN], pa_name[BCTEXTLEN], device[BCTEXTLEN];
650 name[0] = pa_name[0] = device[0] = 0;
651 int arg_len = strlen(arg);
652 while( fgets(line, sizeof(line), pactl) ) {
653 if( !strncasecmp(line, arg, arg_len) ) {
654 char *sp = name, *id = pa_name;
655 for( char *cp=line; *cp && *cp!='\n'; *sp++=*cp++ )
656 *id++ = (*cp>='A' && *cp<='Z') ||
657 (*cp>='a' && *cp<='z') ||
658 (*cp>='0' && *cp<='9') ? *cp : '_';
661 names->append(cstrdup(name));
664 if( sscanf(line, " Name: %s", device) != 1 ) continue;
665 int len = strlen(pa_name);
667 pcm_names->append(cstrdup(pa_name));
668 char alsa_config[BCTEXTLEN];
669 len = snprintf(alsa_config, sizeof(alsa_config),
670 "pcm.!%s {\n type pulse\n device %s\n}\n"
671 "ctl.!%s {\n type pulse\n device %s\n}\n",
672 pa_name, device, pa_name, device);
673 FILE *fp = fmemopen(alsa_config,len,"r");
675 snd_input_stdio_attach(&inp, fp, 1);
676 snd_config_load(snd_config, inp);
677 name[0] = pa_name[0] = device[0] = 0;
678 snd_input_close(inp);