1 #include "audiodevice.h"
3 #include "playbackconfig.h"
4 #include "preferences.h"
5 #include "recordconfig.h"
11 AudioALSA::AudioALSA(AudioDevice *device) : AudioLowLevel(device)
15 AudioALSA::~AudioALSA()
19 void AudioALSA::list_devices(ArrayList<char*> *devices, int pcm_title)
22 int card, err, dev, idx;
23 snd_ctl_card_info_t *info;
24 snd_pcm_info_t *pcminfo;
25 char string[BCTEXTLEN];
26 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
29 snd_ctl_card_info_alloca(&info);
30 snd_pcm_info_alloca(&pcminfo);
34 if((error = snd_card_next(&card)) < 0)
36 printf("AudioALSA::list_devices: %s\n", snd_strerror(error));
43 sprintf(name, "hw:%d", card);
45 if((err = snd_ctl_open(&handle, name, 0)) < 0)
47 printf("AudioALSA::list_devices (%i): %s", card, snd_strerror(err));
51 if((err = snd_ctl_card_info(handle, info)) < 0)
53 printf("AudioALSA::list_devices (%i): %s", card, snd_strerror(err));
54 snd_ctl_close(handle);
63 if(snd_ctl_pcm_next_device(handle, &dev) < 0)
64 printf("AudioALSA::list_devices: snd_ctl_pcm_next_device");
69 snd_pcm_info_set_device(pcminfo, dev);
70 snd_pcm_info_set_subdevice(pcminfo, 0);
71 snd_pcm_info_set_stream(pcminfo, stream);
73 if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0)
76 printf("AudioALSA::list_devices (%i): %s", card, snd_strerror(err));
82 // sprintf(string, "plug:%d,%d", card, dev);
83 printf("AudioALSA::list_devices: %s\n", snd_ctl_card_info_get_name(info));
84 strcpy(string, "cards.pcm.front");
88 sprintf(string, "%s #%d",
89 snd_ctl_card_info_get_name(info),
93 char *result = devices->append(new char[strlen(string) + 1]);
94 strcpy(result, string);
97 snd_ctl_close(handle);
99 if(snd_card_next(&card) < 0)
101 printf("AudioALSA::list_devices: snd_card_next");
106 // snd_ctl_card_info_free(info);
107 // snd_pcm_info_free(pcminfo);
110 void AudioALSA::translate_name(char *output, char *input)
112 ArrayList<char*> titles;
113 ArrayList<char*> pcm_titles;
115 list_devices(&titles, 0);
116 list_devices(&pcm_titles, 1);
118 sprintf(output, "default");
119 for(int i = 0; i < titles.total; i++)
121 //printf("AudioALSA::translate_name %s %s\n", titles.values[i], pcm_titles.values[i]);
122 if(!strcasecmp(titles.values[i], input))
124 strcpy(output, pcm_titles.values[i]);
129 titles.remove_all_objects();
130 pcm_titles.remove_all_objects();
133 snd_pcm_format_t AudioALSA::translate_format(int format)
138 return SND_PCM_FORMAT_S8;
141 return SND_PCM_FORMAT_S16_LE;
144 return SND_PCM_FORMAT_S24_LE;
147 return SND_PCM_FORMAT_S32_LE;
152 void AudioALSA::set_params(snd_pcm_t *dsp,
158 snd_pcm_hw_params_t *params;
159 snd_pcm_sw_params_t *swparams;
162 printf("AudioALSA::set_params 1\n");
163 snd_pcm_hw_params_alloca(¶ms);
164 printf("AudioALSA::set_params 1\n");
165 snd_pcm_sw_params_alloca(&swparams);
166 printf("AudioALSA::set_params 1 %p %p\n", dsp, params);
167 err = snd_pcm_hw_params_any(dsp, params);
169 printf("AudioALSA::set_params 1\n");
172 printf("AudioALSA::set_params: no PCM configurations available\n");
176 printf("AudioALSA::set_params 1\n");
177 snd_pcm_hw_params_set_access(dsp,
179 SND_PCM_ACCESS_RW_INTERLEAVED);
180 snd_pcm_hw_params_set_format(dsp,
182 translate_format(bits));
183 snd_pcm_hw_params_set_channels(dsp,
186 snd_pcm_hw_params_set_rate_near(dsp,
191 printf("AudioALSA::set_params 1\n");
192 // Buffers written must be equal to period_time
193 int buffer_time = (int)((double)samples / samplerate * 1000000 * 2 + 0.5);
194 int period_time = buffer_time / 2;
195 buffer_time = snd_pcm_hw_params_set_buffer_time_near(dsp,
199 period_time = snd_pcm_hw_params_set_period_time_near(dsp,
203 err = snd_pcm_hw_params(dsp, params);
206 printf("AudioALSA::set_params: hw_params failed\n");
210 printf("AudioALSA::set_params 1\n");
211 int chunk_size = snd_pcm_hw_params_get_period_size(params, 0);
212 int buffer_size = snd_pcm_hw_params_get_buffer_size(params);
214 printf("AudioALSA::set_params 1\n");
215 snd_pcm_sw_params_current(dsp, swparams);
216 size_t xfer_align = 1 /* snd_pcm_sw_params_get_xfer_align(swparams) */;
217 unsigned int sleep_min = 0;
218 err = snd_pcm_sw_params_set_sleep_min(dsp, swparams, sleep_min);
220 err = snd_pcm_sw_params_set_avail_min(dsp, swparams, n);
221 err = snd_pcm_sw_params_set_xfer_align(dsp, swparams, xfer_align);
222 if(snd_pcm_sw_params(dsp, swparams) < 0)
224 printf("AudioALSA::set_params: snd_pcm_sw_params failed\n");
227 printf("AudioALSA::set_params 1\n");
228 device->device_buffer = buffer_size /
232 printf("AudioALSA::set_params 2 %d %d\n", samples, device->device_buffer);
234 // snd_pcm_hw_params_free(params);
235 // snd_pcm_sw_params_free(swparams);
238 int AudioALSA::open_input()
240 char pcm_name[BCTEXTLEN];
241 snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
245 //printf("AudioALSA::open_input 1\n");
246 device->in_channels = device->in_config->alsa_in_channels;
247 device->in_bits = device->in_config->alsa_in_bits;
248 //printf("AudioALSA::open_input 1\n");
250 translate_name(pcm_name, device->in_config->alsa_in_device);
251 //printf("AudioALSA::open_input 1\n");
253 err = snd_pcm_open(&dsp_in, pcm_name, stream, open_mode);
254 //printf("AudioALSA::open_input 1\n");
258 printf("AudioALSA::open_input: %s\n", snd_strerror(err));
261 //printf("AudioALSA::open_input 1\n");
264 device->in_config->alsa_in_channels,
265 device->in_config->alsa_in_bits,
266 device->in_samplerate,
268 //printf("AudioALSA::open_input 2\n");
272 int AudioALSA::open_output()
274 char pcm_name[BCTEXTLEN];
275 snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
279 device->out_channels = device->out_config->alsa_out_channels;
280 device->out_bits = device->out_config->alsa_out_bits;
282 translate_name(pcm_name, device->out_config->alsa_out_device);
284 err = snd_pcm_open(&dsp_out, pcm_name, stream, open_mode);
288 printf("AudioALSA::open_output %s: %s\n", pcm_name, snd_strerror(err));
293 device->out_config->alsa_out_channels,
294 device->out_config->alsa_out_bits,
295 device->out_samplerate,
296 device->out_samples);
300 int AudioALSA::open_duplex()
302 // ALSA always opens 2 devices
307 int AudioALSA::close_all()
311 snd_pcm_reset(dsp_in);
312 snd_pcm_drop(dsp_in);
313 snd_pcm_drain(dsp_in);
314 snd_pcm_close(dsp_in);
318 snd_pcm_close(dsp_out);
322 snd_pcm_close(dsp_duplex);
327 int64_t AudioALSA::device_position()
332 int AudioALSA::read_buffer(char *buffer, int size)
334 //printf("AudioALSA::read_buffer 1\n");
335 snd_pcm_readi(get_input(),
337 size / (device->in_bits / 8) / device->in_channels);
338 //printf("AudioALSA::read_buffer 2\n");
342 int AudioALSA::write_buffer(char *buffer, int size)
344 // Buffers written must be equal to period_time
345 if(snd_pcm_writei(get_output(),
347 size / (device->out_bits / 8) / device->out_channels) < 0)
349 printf("AudioALSA::write_buffer: failed\n");
354 int AudioALSA::flush_device()
356 snd_pcm_drain(get_output());
360 int AudioALSA::interrupt_playback()
367 snd_pcm_t* AudioALSA::get_output()
369 if(device->w) return dsp_out;
371 if(device->d) return dsp_duplex;
375 snd_pcm_t* AudioALSA::get_input()
377 if(device->r) return dsp_in;
379 if(device->d) return dsp_duplex;