mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
More completion.
This commit is contained in:
parent
9105bb7fcd
commit
aa3536961b
2 changed files with 175 additions and 28 deletions
|
|
@ -24,8 +24,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ALSA_PCM_SIMPLE_H
|
#ifndef __ALSA_PCM_ORDINARY_H
|
||||||
#define __ALSA_PCM_SIMPLE_H
|
#define __ALSA_PCM_ORDINARY_H
|
||||||
|
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ enum sndo_pcm_latency_type {
|
||||||
(estimated latency in one direction 350ms) (default) */
|
(estimated latency in one direction 350ms) (default) */
|
||||||
SNDO_PCM_LATENCY_NORMAL = 0,
|
SNDO_PCM_LATENCY_NORMAL = 0,
|
||||||
/** medium latency - software phones etc.
|
/** medium latency - software phones etc.
|
||||||
(estimated latency in one direction 50ms) */
|
(estimated latency in one direction maximally 50ms) */
|
||||||
SNDO_PCM_LATENCY_MEDIUM,
|
SNDO_PCM_LATENCY_MEDIUM,
|
||||||
/** realtime latency - realtime applications (effect processors etc.)
|
/** realtime latency - realtime applications (effect processors etc.)
|
||||||
(estimated latency in one direction 5ms) */
|
(estimated latency in one direction 5ms) */
|
||||||
|
|
@ -60,6 +60,8 @@ enum sndo_pcm_xrun_type {
|
||||||
|
|
||||||
typedef struct sndo_pcm sndo_pcm_t;
|
typedef struct sndo_pcm sndo_pcm_t;
|
||||||
|
|
||||||
|
typedef int (sndo_pcm_engine_callback_t)(sndo_pcm_t *pcm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -70,15 +72,15 @@ extern "C" {
|
||||||
* \{
|
* \{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int sndo_pcm_open(sndo_pcm_t **pcm, const char *playback_name, const char *capture_name, snd_config_t *lconf);
|
int sndo_pcm_open(sndo_pcm_t **pcm, const char *playback_name, const char *capture_name, struct alisp_cfg *lconf);
|
||||||
int sndo_pcm_close(sndo_pcm_t *pcm);
|
int sndo_pcm_close(sndo_pcm_t *pcm);
|
||||||
int sndo_pcm_poll_descriptors_count(sndo_pcm_t *pcm);
|
int sndo_pcm_poll_descriptors_count(sndo_pcm_t *pcm);
|
||||||
int sndo_pcm_poll_descriptors(sndo_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
|
int sndo_pcm_poll_descriptors(sndo_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
|
||||||
int sndo_pcm_poll_descriptors_revents(sndo_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
|
|
||||||
int sndo_pcm_start(sndo_pcm_t *pcm);
|
int sndo_pcm_start(sndo_pcm_t *pcm);
|
||||||
int sndo_pcm_drop(sndo_pcm_t *pcm);
|
int sndo_pcm_drop(sndo_pcm_t *pcm);
|
||||||
int sndo_pcm_drain(sndo_pcm_t *pcm);
|
int sndo_pcm_drain(sndo_pcm_t *pcm);
|
||||||
int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp);
|
||||||
|
int sndo_pcm_transfer_block(sndo_pcm_t *pcm, snd_pcm_uframes_t *tblock);
|
||||||
int sndo_pcm_resume(sndo_pcm_t *pcm);
|
int sndo_pcm_resume(sndo_pcm_t *pcm);
|
||||||
int sndo_pcm_wait(sndo_pcm_t *pcm, int timeout);
|
int sndo_pcm_wait(sndo_pcm_t *pcm, int timeout);
|
||||||
snd_pcm_t *sndo_pcm_raw_playback(sndo_pcm_t *pcm);
|
snd_pcm_t *sndo_pcm_raw_playback(sndo_pcm_t *pcm);
|
||||||
|
|
@ -121,8 +123,23 @@ snd_pcm_sframes_t sndo_pcm_cio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup PCM_ordinary_engine Callback like engine
|
||||||
|
* \ingroup PCM_ordinary
|
||||||
|
* See the \ref pcm_ordinary page for more details.
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
int sndo_pcm_set_private_data(sndo_pcm_t *pcm, void *private_data);
|
||||||
|
int sndo_pcm_get_private_data(sndo_pcm_t *pcm, void **private_data);
|
||||||
|
int sndo_pcm_engine(sndo_pcm_t *pcm,
|
||||||
|
sndo_pcm_engine_callback_t *playback,
|
||||||
|
sndo_pcm_engine_callback_t *capture);
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __ALSA_PCM_SIMPLE_H */
|
#endif /* __ALSA_PCM_ORDINARY_H */
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* \ingroup PCM_ordinary
|
* \ingroup PCM_ordinary
|
||||||
* \brief Ordinary PCM interface
|
* \brief Ordinary PCM interface
|
||||||
* \author Jaroslav Kysela <perex@suse.cz>
|
* \author Jaroslav Kysela <perex@suse.cz>
|
||||||
* \date 2003
|
* \date 2003,2004
|
||||||
*
|
*
|
||||||
* Ordinary PCM interface is a high level abtraction for
|
* Ordinary PCM interface is a high level abtraction for
|
||||||
* digital audio streaming.
|
* digital audio streaming.
|
||||||
|
|
@ -56,6 +56,7 @@ Write something here
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "asoundlib.h"
|
#include "asoundlib.h"
|
||||||
|
#include "alisp.h"
|
||||||
#include "pcm_ordinary.h"
|
#include "pcm_ordinary.h"
|
||||||
|
|
||||||
struct sndo_pcm {
|
struct sndo_pcm {
|
||||||
|
|
@ -70,6 +71,12 @@ struct sndo_pcm {
|
||||||
unsigned int samplebytes;
|
unsigned int samplebytes;
|
||||||
snd_pcm_uframes_t p_offset;
|
snd_pcm_uframes_t p_offset;
|
||||||
snd_pcm_uframes_t c_offset;
|
snd_pcm_uframes_t c_offset;
|
||||||
|
snd_pcm_uframes_t p_period_size;
|
||||||
|
snd_pcm_uframes_t c_period_size;
|
||||||
|
snd_pcm_uframes_t transfer_block;
|
||||||
|
snd_pcm_uframes_t ring_size;
|
||||||
|
enum sndo_pcm_latency_type latency;
|
||||||
|
enum sndo_pcm_xrun_type xrun;
|
||||||
int setting_up;
|
int setting_up;
|
||||||
int initialized;
|
int initialized;
|
||||||
};
|
};
|
||||||
|
|
@ -95,7 +102,7 @@ static inline int sndo_pcm_check_setup(sndo_pcm_t *pcm)
|
||||||
int sndo_pcm_open(sndo_pcm_t **ppcm,
|
int sndo_pcm_open(sndo_pcm_t **ppcm,
|
||||||
const char *playback_name,
|
const char *playback_name,
|
||||||
const char *capture_name,
|
const char *capture_name,
|
||||||
snd_config_t *lconf)
|
struct alisp_cfg *lconf)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
sndo_pcm_t *pcm;
|
sndo_pcm_t *pcm;
|
||||||
|
|
@ -122,12 +129,12 @@ int sndo_pcm_open(sndo_pcm_t **ppcm,
|
||||||
goto __end;
|
goto __end;
|
||||||
if (lconf) {
|
if (lconf) {
|
||||||
if (playback_name) {
|
if (playback_name) {
|
||||||
err = snd_pcm_open_lconf(&pcm->playback, playback_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK, lconf);
|
err = snd_pcm_open_lconf(&pcm->playback, playback_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto __end;
|
goto __end;
|
||||||
}
|
}
|
||||||
if (capture_name) {
|
if (capture_name) {
|
||||||
err = snd_pcm_open_lconf(&pcm->capture, playback_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK, lconf);
|
err = snd_pcm_open_lconf(&pcm->capture, playback_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK, NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto __end;
|
goto __end;
|
||||||
}
|
}
|
||||||
|
|
@ -149,8 +156,6 @@ int sndo_pcm_open(sndo_pcm_t **ppcm,
|
||||||
goto __end;
|
goto __end;
|
||||||
pcm->master = pcm->playback;
|
pcm->master = pcm->playback;
|
||||||
}
|
}
|
||||||
if (sndo_pcm_param_reset(pcm) >= 0)
|
|
||||||
*ppcm = pcm;
|
|
||||||
__end:
|
__end:
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
sndo_pcm_close(pcm);
|
sndo_pcm_close(pcm);
|
||||||
|
|
@ -262,6 +267,11 @@ int sndo_pcm_poll_descriptors_revents(sndo_pcm_t *pcm, struct pollfd *pfds, unsi
|
||||||
*/
|
*/
|
||||||
int sndo_pcm_start(sndo_pcm_t *pcm)
|
int sndo_pcm_start(sndo_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = sndo_pcm_check_setup(pcm);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
/* the streams are linked, so use only one stream */
|
/* the streams are linked, so use only one stream */
|
||||||
return snd_pcm_start(pcm->master);
|
return snd_pcm_start(pcm->master);
|
||||||
}
|
}
|
||||||
|
|
@ -307,11 +317,14 @@ int sndo_pcm_drain(sndo_pcm_t *pcm)
|
||||||
*/
|
*/
|
||||||
int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err;
|
||||||
snd_pcm_sframes_t pdelay, cdelay;
|
snd_pcm_sframes_t pdelay, cdelay;
|
||||||
|
|
||||||
assert(pcm);
|
assert(pcm);
|
||||||
assert(delayp);
|
assert(delayp);
|
||||||
|
err = sndo_pcm_check_setup(pcm);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
if (pcm->playback)
|
if (pcm->playback)
|
||||||
err = snd_pcm_avail_update(pcm->playback);
|
err = snd_pcm_avail_update(pcm->playback);
|
||||||
if (err >= 0 && pcm->capture)
|
if (err >= 0 && pcm->capture)
|
||||||
|
|
@ -326,6 +339,27 @@ int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Obtain transfer block size (aka period size)
|
||||||
|
* \param pcm ordinary PCM handle
|
||||||
|
* \param tblock Returned transfer block size in frames
|
||||||
|
* \return 0 on success otherwise a negative error code
|
||||||
|
*
|
||||||
|
* All read/write operations must use this transfer block.
|
||||||
|
*/
|
||||||
|
int sndo_pcm_transfer_block(sndo_pcm_t *pcm, snd_pcm_uframes_t *tblock)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
assert(pcm);
|
||||||
|
assert(tblock);
|
||||||
|
err = sndo_pcm_check_setup(pcm);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
*tblock = pcm->transfer_block;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Resume from suspend, no samples are lost
|
* \brief Resume from suspend, no samples are lost
|
||||||
* \param pcm ordinary PCM handle
|
* \param pcm ordinary PCM handle
|
||||||
|
|
@ -413,6 +447,10 @@ int sndo_pcm_param_reset(sndo_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
err = sndo_pcm_drain(pcm);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
pcm->initialized = 0;
|
||||||
if (pcm->playback) {
|
if (pcm->playback) {
|
||||||
err = snd_pcm_hw_params_any(pcm->playback, pcm->p_hw_params);
|
err = snd_pcm_hw_params_any(pcm->playback, pcm->p_hw_params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
@ -577,6 +615,9 @@ int sndo_pcm_param_format(sndo_pcm_t *pcm, snd_pcm_format_t format, snd_pcm_subf
|
||||||
* \param latency requested latency
|
* \param latency requested latency
|
||||||
* \param used_latency returned real latency in frames
|
* \param used_latency returned real latency in frames
|
||||||
* \return 0 on success otherwise a negative error code
|
* \return 0 on success otherwise a negative error code
|
||||||
|
*
|
||||||
|
* Note that the result value is only approximate and for one direction.
|
||||||
|
* For example, hardware FIFOs are not counted etc.
|
||||||
*/
|
*/
|
||||||
int sndo_pcm_param_latency(sndo_pcm_t *pcm, enum sndo_pcm_latency_type latency, snd_pcm_uframes_t *used_latency)
|
int sndo_pcm_param_latency(sndo_pcm_t *pcm, enum sndo_pcm_latency_type latency, snd_pcm_uframes_t *used_latency)
|
||||||
{
|
{
|
||||||
|
|
@ -585,7 +626,13 @@ int sndo_pcm_param_latency(sndo_pcm_t *pcm, enum sndo_pcm_latency_type latency,
|
||||||
err = sndo_pcm_setup(pcm);
|
err = sndo_pcm_setup(pcm);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return -EIO;
|
pcm->latency = latency;
|
||||||
|
err = sndo_pcm_check_setup(pcm);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
if (used_latency)
|
||||||
|
*used_latency = pcm->ring_size;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -601,7 +648,8 @@ int sndo_pcm_param_xrun(sndo_pcm_t *pcm, enum sndo_pcm_xrun_type xrun)
|
||||||
err = sndo_pcm_setup(pcm);
|
err = sndo_pcm_setup(pcm);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return -EIO;
|
pcm->xrun = xrun;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -622,7 +670,12 @@ int sndo_pcm_pio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *
|
||||||
err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames);
|
err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
if (*frames < pcm->transfer_block) {
|
||||||
|
frames = 0;
|
||||||
|
} else {
|
||||||
|
*frames -= *frames % pcm->transfer_block;
|
||||||
*ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->p_offset * pcm->samplebytes;
|
*ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->p_offset * pcm->samplebytes;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -634,6 +687,10 @@ int sndo_pcm_pio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *
|
||||||
*/
|
*/
|
||||||
snd_pcm_sframes_t sndo_pcm_pio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
snd_pcm_sframes_t sndo_pcm_pio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||||
{
|
{
|
||||||
|
if (frames <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (frames % pcm->transfer_block)
|
||||||
|
return -EINVAL;
|
||||||
return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
|
return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -656,8 +713,13 @@ int sndo_pcm_pio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t
|
||||||
err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames);
|
err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
if (*frames < pcm->transfer_block) {
|
||||||
|
frames = 0;
|
||||||
|
} else {
|
||||||
|
*frames -= *frames % pcm->transfer_block;
|
||||||
for (ch = 0; ch < pcm->channels; ch++)
|
for (ch = 0; ch < pcm->channels; ch++)
|
||||||
ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->p_offset * pcm->samplebytes;
|
ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->p_offset * pcm->samplebytes;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -669,6 +731,10 @@ int sndo_pcm_pio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t
|
||||||
*/
|
*/
|
||||||
snd_pcm_sframes_t sndo_pcm_pio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
snd_pcm_sframes_t sndo_pcm_pio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||||
{
|
{
|
||||||
|
if (frames <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (frames % pcm->transfer_block)
|
||||||
|
return -EINVAL;
|
||||||
return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
|
return snd_pcm_mmap_commit(pcm->playback, pcm->p_offset, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -690,7 +756,12 @@ int sndo_pcm_cio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *
|
||||||
err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames);
|
err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
if (*frames < pcm->transfer_block) {
|
||||||
|
frames = 0;
|
||||||
|
} else {
|
||||||
|
*frames -= *frames % pcm->transfer_block;
|
||||||
*ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->c_offset * pcm->samplebytes;
|
*ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->c_offset * pcm->samplebytes;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -702,6 +773,10 @@ int sndo_pcm_cio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *
|
||||||
*/
|
*/
|
||||||
snd_pcm_sframes_t sndo_pcm_cio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
snd_pcm_sframes_t sndo_pcm_cio_iend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||||
{
|
{
|
||||||
|
if (frames <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (frames % pcm->transfer_block)
|
||||||
|
return -EINVAL;
|
||||||
return snd_pcm_mmap_commit(pcm->capture, pcm->p_offset, frames);
|
return snd_pcm_mmap_commit(pcm->capture, pcm->p_offset, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -724,8 +799,13 @@ int sndo_pcm_cio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t
|
||||||
err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames);
|
err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
if (*frames < pcm->transfer_block) {
|
||||||
|
frames = 0;
|
||||||
|
} else {
|
||||||
|
*frames -= *frames % pcm->transfer_block;
|
||||||
for (ch = 0; ch < pcm->channels; ch++)
|
for (ch = 0; ch < pcm->channels; ch++)
|
||||||
ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->c_offset * pcm->samplebytes;
|
ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->c_offset * pcm->samplebytes;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -737,6 +817,10 @@ int sndo_pcm_cio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t
|
||||||
*/
|
*/
|
||||||
snd_pcm_sframes_t sndo_pcm_cio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
snd_pcm_sframes_t sndo_pcm_cio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||||
{
|
{
|
||||||
|
if (frames <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (frames % pcm->transfer_block)
|
||||||
|
return -EINVAL;
|
||||||
return snd_pcm_mmap_commit(pcm->capture, pcm->c_offset, frames);
|
return snd_pcm_mmap_commit(pcm->capture, pcm->c_offset, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -746,8 +830,11 @@ snd_pcm_sframes_t sndo_pcm_cio_nend(sndo_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||||
|
|
||||||
static int sndo_pcm_setup(sndo_pcm_t *pcm)
|
static int sndo_pcm_setup(sndo_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
if (pcm->initialized)
|
int err;
|
||||||
return 0;
|
|
||||||
|
err = sndo_pcm_drain(pcm);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
if (!pcm->setting_up) {
|
if (!pcm->setting_up) {
|
||||||
int err = sndo_pcm_param_reset(pcm);
|
int err = sndo_pcm_param_reset(pcm);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
@ -761,19 +848,56 @@ static int sndo_pcm_initialize(sndo_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
snd_pcm_uframes_t boundary;
|
snd_pcm_uframes_t boundary;
|
||||||
snd_pcm_uframes_t avail_min = 1; /* FIXME */
|
snd_pcm_uframes_t p_period_size = ~0UL, c_period_size = ~0UL;
|
||||||
|
snd_pcm_uframes_t p_buffer_size = ~0UL, c_buffer_size = ~0UL;
|
||||||
|
|
||||||
|
if (pcm->playback) {
|
||||||
|
err = snd_pcm_hw_params(pcm->playback, pcm->p_hw_params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_hw_params_get_period_size(pcm->p_hw_params, &p_period_size, NULL);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_hw_params_get_buffer_size(pcm->p_hw_params, &p_buffer_size);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (pcm->capture) {
|
||||||
|
err = snd_pcm_hw_params(pcm->capture, pcm->c_hw_params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_hw_params_get_period_size(pcm->c_hw_params, &c_period_size, NULL);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_hw_params_get_buffer_size(pcm->c_hw_params, &c_buffer_size);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (p_period_size < c_period_size)
|
||||||
|
pcm->transfer_block = p_period_size;
|
||||||
|
else
|
||||||
|
pcm->transfer_block = c_period_size;
|
||||||
|
if (p_buffer_size < c_buffer_size)
|
||||||
|
pcm->ring_size = p_buffer_size;
|
||||||
|
else
|
||||||
|
pcm->ring_size = c_buffer_size;
|
||||||
if (pcm->playback) {
|
if (pcm->playback) {
|
||||||
err = snd_pcm_sw_params_get_boundary(pcm->p_sw_params, &boundary);
|
err = snd_pcm_sw_params_get_boundary(pcm->p_sw_params, &boundary);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_sw_params_set_start_threshold(pcm->capture, pcm->p_sw_params, boundary);
|
err = snd_pcm_sw_params_set_start_threshold(pcm->playback, pcm->p_sw_params, boundary);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_sw_params_set_stop_threshold(pcm->playback, pcm->p_sw_params, pcm->xrun == SNDO_PCM_XRUN_IGNORE ? boundary : pcm->ring_size);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_sw_params_set_xfer_align(pcm->playback, pcm->p_sw_params, 1);
|
err = snd_pcm_sw_params_set_xfer_align(pcm->playback, pcm->p_sw_params, 1);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_sw_params_set_avail_min(pcm->playback, pcm->p_sw_params, avail_min);
|
err = snd_pcm_sw_params_set_avail_min(pcm->playback, pcm->p_sw_params, pcm->transfer_block);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_sw_params(pcm->playback, pcm->p_sw_params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -782,12 +906,18 @@ static int sndo_pcm_initialize(sndo_pcm_t *pcm)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_sw_params_set_start_threshold(pcm->capture, pcm->c_sw_params, boundary);
|
err = snd_pcm_sw_params_set_start_threshold(pcm->capture, pcm->c_sw_params, boundary);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_sw_params_set_stop_threshold(pcm->capture, pcm->c_sw_params, pcm->xrun == SNDO_PCM_XRUN_IGNORE ? boundary : pcm->ring_size);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_sw_params_set_xfer_align(pcm->capture, pcm->c_sw_params, 1);
|
err = snd_pcm_sw_params_set_xfer_align(pcm->capture, pcm->c_sw_params, 1);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_sw_params_set_avail_min(pcm->capture, pcm->c_sw_params, avail_min);
|
err = snd_pcm_sw_params_set_avail_min(pcm->capture, pcm->c_sw_params, pcm->transfer_block);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_sw_params(pcm->capture, pcm->c_sw_params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue