mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Better PCM mmap API. Fixed pcm_multi
This commit is contained in:
parent
c4f95f48c3
commit
6a3b962d06
16 changed files with 279 additions and 279 deletions
|
|
@ -455,8 +455,10 @@ static int pcm_shm_cmd(client_t *client)
|
|||
ctrl->result = snd_pcm_munmap(pcm);
|
||||
break;
|
||||
}
|
||||
case SND_PCM_IOCTL_MMAP_FORWARD:
|
||||
ctrl->result = snd_pcm_mmap_forward(pcm, ctrl->u.mmap_forward.frames);
|
||||
case SND_PCM_IOCTL_MMAP_COMMIT:
|
||||
ctrl->result = snd_pcm_mmap_commit(pcm,
|
||||
ctrl->u.mmap_commit.offset,
|
||||
ctrl->u.mmap_commit.frames);
|
||||
ctrl->appl_ptr = *pcm->appl_ptr;
|
||||
break;
|
||||
case SND_PCM_IOCTL_POLL_DESCRIPTOR:
|
||||
|
|
@ -610,7 +612,7 @@ static int ctl_shm_cmd(client_t *client)
|
|||
ctrl->result = snd_ctl_pcm_next_device(ctl, &ctrl->u.device);
|
||||
break;
|
||||
case SND_CTL_IOCTL_PCM_SURROUND_NEXT_DEVICE:
|
||||
ctrl->result = snd_ctl_pcm_surround_next_device(ctl, &ctrl->u.surround.type, &ctrl->u.surround.device);
|
||||
ctrl->result = snd_ctl_pcm_surround_next_device(ctl, ctrl->u.surround.type, &ctrl->u.surround.device);
|
||||
break;
|
||||
case SNDRV_CTL_IOCTL_PCM_INFO:
|
||||
ctrl->result = snd_ctl_pcm_info(ctl, &ctrl->u.pcm_info);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ typedef enum _snd_transport_type {
|
|||
#define SND_PCM_IOCTL_STATE _IO ('A', 0xf1)
|
||||
#define SND_PCM_IOCTL_MMAP _IO ('A', 0xf2)
|
||||
#define SND_PCM_IOCTL_MUNMAP _IO ('A', 0xf3)
|
||||
#define SND_PCM_IOCTL_MMAP_FORWARD _IO ('A', 0xf4)
|
||||
#define SND_PCM_IOCTL_MMAP_COMMIT _IO ('A', 0xf4)
|
||||
#define SND_PCM_IOCTL_AVAIL_UPDATE _IO ('A', 0xf5)
|
||||
#define SND_PCM_IOCTL_ASYNC _IO ('A', 0xf6)
|
||||
#define SND_PCM_IOCTL_CLOSE _IO ('A', 0xf7)
|
||||
|
|
@ -77,8 +77,9 @@ typedef struct {
|
|||
int fd;
|
||||
} link;
|
||||
struct {
|
||||
snd_pcm_uframes_t offset;
|
||||
snd_pcm_uframes_t frames;
|
||||
} mmap_forward;
|
||||
} mmap_commit;
|
||||
} u;
|
||||
char data[0];
|
||||
} snd_pcm_shm_ctrl_t;
|
||||
|
|
@ -101,7 +102,7 @@ typedef struct {
|
|||
} async;
|
||||
int device;
|
||||
struct {
|
||||
int type;
|
||||
snd_pcm_surround_type_t type;
|
||||
int device;
|
||||
} surround;
|
||||
int subscribe_events;
|
||||
|
|
|
|||
|
|
@ -381,16 +381,12 @@ int snd_pcm_sw_params_dump(snd_pcm_sw_params_t *params, snd_output_t *out);
|
|||
int snd_pcm_status_dump(snd_pcm_status_t *status, snd_output_t *out);
|
||||
|
||||
/* mmap */
|
||||
const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm);
|
||||
const snd_pcm_channel_area_t *snd_pcm_mmap_running_areas(snd_pcm_t *pcm);
|
||||
const snd_pcm_channel_area_t *snd_pcm_mmap_stopped_areas(snd_pcm_t *pcm);
|
||||
snd_pcm_sframes_t snd_pcm_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size);
|
||||
snd_pcm_uframes_t snd_pcm_mmap_offset(snd_pcm_t *pcm);
|
||||
snd_pcm_uframes_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
|
||||
int snd_pcm_mmap_begin(snd_pcm_t *pcm,
|
||||
const snd_pcm_channel_area_t **areas,
|
||||
snd_pcm_uframes_t *offset,
|
||||
snd_pcm_uframes_t *frames);
|
||||
int snd_pcm_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t frames);
|
||||
|
||||
const char *snd_pcm_stream_name(snd_pcm_stream_t stream);
|
||||
const char *snd_pcm_access_name(snd_pcm_access_t _access);
|
||||
|
|
|
|||
100
src/pcm/pcm.c
100
src/pcm/pcm.c
|
|
@ -1098,23 +1098,6 @@ snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm)
|
|||
return pcm->fast_ops->avail_update(pcm->fast_op_arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Advance PCM frame position in mmap buffer
|
||||
* \param pcm PCM handle
|
||||
* \param size movement size
|
||||
* \return a positive number of actual movement size otherwise a negative
|
||||
* error code
|
||||
*
|
||||
* On playback does all the actions needed to transport the frames across
|
||||
* underlying layers.
|
||||
*/
|
||||
snd_pcm_sframes_t snd_pcm_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
{
|
||||
assert(size > 0);
|
||||
assert(size <= snd_pcm_mmap_avail(pcm));
|
||||
return pcm->fast_ops->mmap_forward(pcm->fast_op_arg, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Silence an area
|
||||
* \param dst_area area specification
|
||||
|
|
@ -3932,64 +3915,57 @@ void snd_pcm_info_set_stream(snd_pcm_info_t *obj, snd_pcm_stream_t val)
|
|||
obj->stream = snd_enum_to_int(val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get channel areas for a given PCM when running
|
||||
* \brief Application request to access a portion of mmap area
|
||||
* \param pcm PCM handle
|
||||
* \return pointer to channel areas (one for each channel)
|
||||
* \param areas Returned mmap channel areas
|
||||
* \param offset Returned mmap area offset
|
||||
* \param size mmap area portion size (wanted on entry, contiguous
|
||||
available on exit)
|
||||
* \return 0 on success otherwise a negative error code
|
||||
*/
|
||||
const snd_pcm_channel_area_t *snd_pcm_mmap_running_areas(snd_pcm_t *pcm)
|
||||
{
|
||||
return pcm->running_areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get channel areas for a given PCM when stopped
|
||||
* \param pcm PCM handle
|
||||
* \return pointer to channel areas (one for each channel)
|
||||
*/
|
||||
const snd_pcm_channel_area_t *snd_pcm_mmap_stopped_areas(snd_pcm_t *pcm)
|
||||
{
|
||||
return pcm->stopped_areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get appropriate channel areas for a given PCM according to its state (running or stopped)
|
||||
* \param pcm PCM handle
|
||||
* \return pointer to channel areas (one for each channel)
|
||||
*/
|
||||
const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm)
|
||||
int snd_pcm_mmap_begin(snd_pcm_t *pcm,
|
||||
const snd_pcm_channel_area_t **areas,
|
||||
snd_pcm_uframes_t *offset,
|
||||
snd_pcm_uframes_t *frames)
|
||||
{
|
||||
snd_pcm_uframes_t cont;
|
||||
snd_pcm_uframes_t avail;
|
||||
snd_pcm_uframes_t f;
|
||||
assert(pcm && areas && offset && frames);
|
||||
if (pcm->stopped_areas &&
|
||||
snd_pcm_state(pcm) != SND_PCM_STATE_RUNNING)
|
||||
return pcm->stopped_areas;
|
||||
return pcm->running_areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Correct frames count according to contiguity consideration inside PCM ring buffer
|
||||
* \param pcm PCM handle
|
||||
* \param frames Frames to transfer
|
||||
* \return Number of contiguous frames transferrable
|
||||
*/
|
||||
snd_pcm_uframes_t snd_pcm_mmap_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||
{
|
||||
assert(pcm);
|
||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
||||
return snd_pcm_mmap_playback_xfer(pcm, frames);
|
||||
*areas = pcm->stopped_areas;
|
||||
else
|
||||
return snd_pcm_mmap_capture_xfer(pcm, frames);
|
||||
*areas = pcm->running_areas;
|
||||
*offset = *pcm->appl_ptr % pcm->buffer_size;
|
||||
avail = snd_pcm_mmap_avail(pcm);
|
||||
f = *frames;
|
||||
if (f > avail)
|
||||
f = avail;
|
||||
cont = pcm->buffer_size - *pcm->appl_ptr % pcm->buffer_size;
|
||||
if (f > cont)
|
||||
f = cont;
|
||||
*frames = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return application offset inside ring buffer
|
||||
* \brief Application has completed the access to area requested with
|
||||
#snd_pcm_mmap_begin
|
||||
* \param pcm PCM handle
|
||||
* \return Offset for frames transfer
|
||||
* \return 0 on success otherwise a negative error code
|
||||
*
|
||||
* To call this with offset/frames values different from that returned
|
||||
* by snd_pcm_mmap_begin has undefined effects and it has to be avoided.
|
||||
*/
|
||||
snd_pcm_uframes_t snd_pcm_mmap_offset(snd_pcm_t *pcm)
|
||||
int snd_pcm_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t frames)
|
||||
{
|
||||
assert(pcm);
|
||||
return *pcm->appl_ptr % pcm->buffer_size;
|
||||
assert(pcm);
|
||||
assert(offset == *pcm->appl_ptr % pcm->buffer_size);
|
||||
assert(frames <= snd_pcm_mmap_avail(pcm));
|
||||
return pcm->fast_ops->mmap_commit(pcm->fast_op_arg, offset, frames);
|
||||
}
|
||||
|
||||
#ifndef DOC_HIDDEN
|
||||
|
|
|
|||
|
|
@ -268,26 +268,19 @@ static snd_pcm_sframes_t snd_pcm_file_readn(snd_pcm_t *pcm, void **bufs, snd_pcm
|
|||
return n;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_file_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_file_t *file = pcm->private_data;
|
||||
snd_pcm_uframes_t ofs = snd_pcm_mmap_offset(pcm);
|
||||
snd_pcm_sframes_t n = snd_pcm_mmap_forward(file->slave, size);
|
||||
snd_pcm_uframes_t xfer = 0;
|
||||
if (n <= 0)
|
||||
return n;
|
||||
while (xfer < (snd_pcm_uframes_t)n) {
|
||||
snd_pcm_uframes_t frames = n - xfer;
|
||||
snd_pcm_uframes_t cont = pcm->buffer_size - ofs;
|
||||
if (frames > cont)
|
||||
frames = cont;
|
||||
snd_pcm_file_add_frames(pcm, snd_pcm_mmap_areas(file->slave), ofs, frames);
|
||||
ofs += frames;
|
||||
if (ofs == pcm->buffer_size)
|
||||
ofs = 0;
|
||||
xfer += frames;
|
||||
}
|
||||
return n;
|
||||
snd_pcm_uframes_t ofs;
|
||||
snd_pcm_uframes_t siz = size;
|
||||
const snd_pcm_channel_area_t *areas;
|
||||
snd_pcm_mmap_begin(file->slave, &areas, &ofs, &siz);
|
||||
assert(ofs == offset && siz == size);
|
||||
snd_pcm_mmap_commit(file->slave, ofs, siz);
|
||||
snd_pcm_file_add_frames(pcm, areas, ofs, siz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_file_avail_update(snd_pcm_t *pcm)
|
||||
|
|
@ -400,7 +393,7 @@ snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
|
|||
readi: snd_pcm_file_readi,
|
||||
readn: snd_pcm_file_readn,
|
||||
avail_update: snd_pcm_file_avail_update,
|
||||
mmap_forward: snd_pcm_file_mmap_forward,
|
||||
mmap_commit: snd_pcm_file_mmap_commit,
|
||||
};
|
||||
|
||||
int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, const char *fname, int fd, const char *fmt, snd_pcm_t *slave, int close_slave)
|
||||
|
|
|
|||
|
|
@ -449,7 +449,9 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_hw_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
if (!(pcm->info & SND_PCM_INFO_MMAP) &&
|
||||
pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
||||
|
|
@ -526,7 +528,7 @@ snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
|
|||
readi: snd_pcm_hw_readi,
|
||||
readn: snd_pcm_hw_readn,
|
||||
avail_update: snd_pcm_hw_avail_update,
|
||||
mmap_forward: snd_pcm_hw_mmap_forward,
|
||||
mmap_commit: snd_pcm_hw_mmap_commit,
|
||||
};
|
||||
|
||||
static int snd_pcm_hw_open_subdevice(snd_pcm_t **pcmp, int card, int device, int subdevice, snd_pcm_stream_t stream, int mode)
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ typedef struct {
|
|||
snd_pcm_sframes_t (*readi)(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t (*readn)(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t (*avail_update)(snd_pcm_t *pcm);
|
||||
snd_pcm_sframes_t (*mmap_forward)(snd_pcm_t *pcm, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t (*mmap_commit)(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size);
|
||||
} snd_pcm_fast_ops_t;
|
||||
|
||||
struct _snd_pcm {
|
||||
|
|
@ -209,9 +209,11 @@ void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
|||
void snd_pcm_mmap_appl_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||
void snd_pcm_mmap_hw_backward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||
void snd_pcm_mmap_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||
snd_pcm_uframes_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm);
|
||||
snd_pcm_uframes_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||
snd_pcm_uframes_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
|
||||
|
||||
snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_mmap_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
|
||||
|
||||
typedef snd_pcm_uframes_t (*snd_pcm_xfer_areas_func_t)(snd_pcm_t *pcm,
|
||||
const snd_pcm_channel_area_t *areas,
|
||||
|
|
@ -279,6 +281,26 @@ static inline snd_pcm_sframes_t snd_pcm_mmap_hw_avail(snd_pcm_t *pcm)
|
|||
return pcm->buffer_size - avail;
|
||||
}
|
||||
|
||||
static inline const snd_pcm_channel_area_t *snd_pcm_mmap_areas(snd_pcm_t *pcm)
|
||||
{
|
||||
if (pcm->stopped_areas &&
|
||||
snd_pcm_state(pcm) != SND_PCM_STATE_RUNNING)
|
||||
return pcm->stopped_areas;
|
||||
return pcm->running_areas;
|
||||
}
|
||||
|
||||
static inline snd_pcm_uframes_t snd_pcm_mmap_offset(snd_pcm_t *pcm)
|
||||
{
|
||||
assert(pcm);
|
||||
return *pcm->appl_ptr % pcm->buffer_size;
|
||||
}
|
||||
|
||||
static inline snd_pcm_uframes_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm)
|
||||
{
|
||||
assert(pcm);
|
||||
return *pcm->hw_ptr % pcm->buffer_size;
|
||||
}
|
||||
|
||||
#define snd_pcm_mmap_playback_delay snd_pcm_mmap_playback_hw_avail
|
||||
#define snd_pcm_mmap_capture_delay snd_pcm_mmap_capture_avail
|
||||
|
||||
|
|
|
|||
|
|
@ -385,11 +385,13 @@ static snd_pcm_sframes_t snd_pcm_meter_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
|
|||
return err;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_meter_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t snd_pcm_meter_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_meter_t *meter = pcm->private_data;
|
||||
snd_pcm_uframes_t old_rptr = *pcm->appl_ptr;
|
||||
snd_pcm_sframes_t result = snd_pcm_mmap_forward(meter->slave, size);
|
||||
snd_pcm_sframes_t result = snd_pcm_mmap_commit(meter->slave, offset, size);
|
||||
if (result <= 0)
|
||||
return result;
|
||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||
|
|
@ -594,7 +596,7 @@ snd_pcm_fast_ops_t snd_pcm_meter_fast_ops = {
|
|||
readi: snd_pcm_mmap_readi,
|
||||
readn: snd_pcm_mmap_readn,
|
||||
avail_update: snd_pcm_meter_avail_update,
|
||||
mmap_forward: snd_pcm_meter_mmap_forward,
|
||||
mmap_commit: snd_pcm_meter_mmap_commit,
|
||||
};
|
||||
|
||||
int snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, unsigned int frequency,
|
||||
|
|
|
|||
|
|
@ -44,36 +44,6 @@ size_t page_align(size_t size)
|
|||
return size;
|
||||
}
|
||||
|
||||
snd_pcm_uframes_t snd_pcm_mmap_playback_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||
{
|
||||
snd_pcm_uframes_t cont;
|
||||
snd_pcm_uframes_t avail = snd_pcm_mmap_playback_avail(pcm);
|
||||
if (avail < frames)
|
||||
frames = avail;
|
||||
cont = pcm->buffer_size - *pcm->appl_ptr % pcm->buffer_size;
|
||||
if (cont < frames)
|
||||
frames = cont;
|
||||
return frames;
|
||||
}
|
||||
|
||||
snd_pcm_uframes_t snd_pcm_mmap_capture_xfer(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||
{
|
||||
snd_pcm_uframes_t cont;
|
||||
snd_pcm_uframes_t avail = snd_pcm_mmap_capture_avail(pcm);
|
||||
if (avail < frames)
|
||||
frames = avail;
|
||||
cont = pcm->buffer_size - *pcm->appl_ptr % pcm->buffer_size;
|
||||
if (cont < frames)
|
||||
frames = cont;
|
||||
return frames;
|
||||
}
|
||||
|
||||
snd_pcm_uframes_t snd_pcm_mmap_hw_offset(snd_pcm_t *pcm)
|
||||
{
|
||||
assert(pcm);
|
||||
return *pcm->hw_ptr % pcm->buffer_size;
|
||||
}
|
||||
|
||||
void snd_pcm_mmap_appl_backward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
|
||||
{
|
||||
snd_pcm_sframes_t appl_ptr = *pcm->appl_ptr;
|
||||
|
|
@ -115,28 +85,18 @@ static snd_pcm_uframes_t snd_pcm_mmap_write_areas(snd_pcm_t *pcm,
|
|||
snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
const snd_pcm_channel_area_t *pcm_areas;
|
||||
snd_pcm_uframes_t pcm_offset;
|
||||
snd_pcm_uframes_t xfer = size;
|
||||
assert(snd_pcm_mmap_playback_avail(pcm) >= size);
|
||||
pcm_areas = snd_pcm_mmap_areas(pcm);
|
||||
pcm_offset = snd_pcm_mmap_offset(pcm);
|
||||
while (size > 0) {
|
||||
const snd_pcm_channel_area_t *pcm_areas;
|
||||
snd_pcm_uframes_t pcm_offset;
|
||||
snd_pcm_uframes_t frames = size;
|
||||
snd_pcm_uframes_t cont = pcm->buffer_size - pcm_offset;
|
||||
int err;
|
||||
if (frames > cont)
|
||||
frames = cont;
|
||||
snd_pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames);
|
||||
snd_pcm_areas_copy(pcm_areas, pcm_offset,
|
||||
areas, offset,
|
||||
pcm->channels,
|
||||
frames, pcm->format);
|
||||
err = snd_pcm_mmap_forward(pcm, frames);
|
||||
assert(err == (snd_pcm_sframes_t)frames);
|
||||
if (frames == cont)
|
||||
pcm_offset = 0;
|
||||
else
|
||||
pcm_offset += frames;
|
||||
snd_pcm_mmap_commit(pcm, pcm_offset, frames);
|
||||
offset += frames;
|
||||
size -= frames;
|
||||
}
|
||||
|
|
@ -148,28 +108,18 @@ static snd_pcm_uframes_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm,
|
|||
snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
const snd_pcm_channel_area_t *pcm_areas;
|
||||
snd_pcm_uframes_t pcm_offset;
|
||||
snd_pcm_uframes_t xfer = size;
|
||||
assert(snd_pcm_mmap_capture_avail(pcm) >= size);
|
||||
pcm_areas = snd_pcm_mmap_areas(pcm);
|
||||
pcm_offset = snd_pcm_mmap_offset(pcm);
|
||||
while (size > 0) {
|
||||
const snd_pcm_channel_area_t *pcm_areas;
|
||||
snd_pcm_uframes_t pcm_offset;
|
||||
snd_pcm_uframes_t frames = size;
|
||||
snd_pcm_uframes_t cont = pcm->buffer_size - pcm_offset;
|
||||
int err;
|
||||
if (frames > cont)
|
||||
frames = cont;
|
||||
snd_pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames);
|
||||
snd_pcm_areas_copy(areas, offset,
|
||||
pcm_areas, pcm_offset,
|
||||
pcm->channels,
|
||||
frames, pcm->format);
|
||||
err = snd_pcm_mmap_forward(pcm, frames);
|
||||
assert(err == (snd_pcm_sframes_t)frames);
|
||||
if (frames == cont)
|
||||
pcm_offset = 0;
|
||||
else
|
||||
pcm_offset += frames;
|
||||
snd_pcm_mmap_commit(pcm, pcm_offset, frames);
|
||||
offset += frames;
|
||||
size -= frames;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ typedef struct {
|
|||
snd_pcm_t *pcm;
|
||||
unsigned int channels_count;
|
||||
int close_slave;
|
||||
int linked;
|
||||
} snd_pcm_multi_slave_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -50,14 +51,12 @@ static int snd_pcm_multi_close(snd_pcm_t *pcm)
|
|||
unsigned int i;
|
||||
int ret = 0;
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
int err;
|
||||
snd_pcm_multi_slave_t *slave = &multi->slaves[i];
|
||||
if (slave->close_slave)
|
||||
err = snd_pcm_close(slave->pcm);
|
||||
else
|
||||
err = snd_pcm_unlink(slave->pcm);
|
||||
if (err < 0)
|
||||
ret = err;
|
||||
if (slave->close_slave) {
|
||||
int err = snd_pcm_close(slave->pcm);
|
||||
if (err < 0)
|
||||
ret = err;
|
||||
}
|
||||
}
|
||||
free(multi->slaves);
|
||||
free(multi->channels);
|
||||
|
|
@ -249,7 +248,7 @@ static int snd_pcm_multi_hw_params_slave(snd_pcm_t *pcm,
|
|||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
snd_pcm_t *slave = multi->slaves[slave_idx].pcm;
|
||||
int err = snd_pcm_hw_refine(slave, sparams);
|
||||
int err = snd_pcm_hw_params(slave, sparams);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = snd_pcm_areas_silence(slave->running_areas, 0, slave->channels, slave->buffer_size, slave->format);
|
||||
|
|
@ -266,20 +265,25 @@ static int snd_pcm_multi_hw_params_slave(snd_pcm_t *pcm,
|
|||
static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
unsigned int k;
|
||||
unsigned int i;
|
||||
snd_pcm_hw_params_t sparams[multi->slaves_count];
|
||||
int err;
|
||||
for (k = 0; k < multi->slaves_count; ++k) {
|
||||
err = snd_pcm_multi_hw_refine_sprepare(pcm, k, &sparams[k]);
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
err = snd_pcm_multi_hw_refine_sprepare(pcm, i, &sparams[i]);
|
||||
assert(err >= 0);
|
||||
err = snd_pcm_multi_hw_refine_schange(pcm, k, params, &sparams[k]);
|
||||
err = snd_pcm_multi_hw_refine_schange(pcm, i, params, &sparams[i]);
|
||||
assert(err >= 0);
|
||||
err = snd_pcm_multi_hw_params_slave(pcm, k, &sparams[k]);
|
||||
err = snd_pcm_multi_hw_params_slave(pcm, i, &sparams[i]);
|
||||
if (err < 0) {
|
||||
snd_pcm_multi_hw_refine_cchange(pcm, k, params, &sparams[k]);
|
||||
snd_pcm_multi_hw_refine_cchange(pcm, i, params, &sparams[i]);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
multi->slaves[0].linked = 0;
|
||||
for (i = 1; i < multi->slaves_count; ++i) {
|
||||
err = snd_pcm_link(multi->slaves[0].pcm, multi->slaves[i].pcm);
|
||||
multi->slaves[i].linked = (err >= 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -293,6 +297,11 @@ static int snd_pcm_multi_hw_free(snd_pcm_t *pcm)
|
|||
int e = snd_pcm_hw_free(slave);
|
||||
if (e < 0)
|
||||
err = e;
|
||||
if (!multi->slaves[i].linked)
|
||||
continue;
|
||||
e = snd_pcm_unlink(slave);
|
||||
if (e < 0)
|
||||
err = e;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
@ -335,44 +344,107 @@ static int snd_pcm_multi_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
|
|||
static snd_pcm_sframes_t snd_pcm_multi_avail_update(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
snd_pcm_t *slave = multi->slaves[0].pcm;
|
||||
return snd_pcm_avail_update(slave);
|
||||
snd_pcm_sframes_t ret = LONG_MAX;
|
||||
unsigned int i;
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
snd_pcm_sframes_t avail;
|
||||
avail = snd_pcm_avail_update(multi->slaves[i].pcm);
|
||||
if (avail < 0)
|
||||
return avail;
|
||||
if (ret > avail)
|
||||
ret = avail;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_prepare(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
return snd_pcm_prepare(multi->slaves[0].pcm);
|
||||
int err = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
if (multi->slaves[i].linked)
|
||||
continue;
|
||||
err = snd_pcm_prepare(multi->slaves[i].pcm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_reset(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
return snd_pcm_reset(multi->slaves[0].pcm);
|
||||
int err = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
if (multi->slaves[i].linked)
|
||||
continue;
|
||||
err = snd_pcm_reset(multi->slaves[i].pcm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_start(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
return snd_pcm_start(multi->slaves[0].pcm);
|
||||
int err = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
if (multi->slaves[i].linked)
|
||||
continue;
|
||||
err = snd_pcm_start(multi->slaves[i].pcm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_drop(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
return snd_pcm_drop(multi->slaves[0].pcm);
|
||||
int err = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
if (multi->slaves[i].linked)
|
||||
continue;
|
||||
err = snd_pcm_drop(multi->slaves[i].pcm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_drain(snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
return snd_pcm_drain(multi->slaves[0].pcm);
|
||||
int err = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
if (multi->slaves[i].linked)
|
||||
continue;
|
||||
err = snd_pcm_drain(multi->slaves[i].pcm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_pause(snd_pcm_t *pcm, int enable)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
return snd_pcm_pause(multi->slaves[0].pcm, enable);
|
||||
int err = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
if (multi->slaves[i].linked)
|
||||
continue;
|
||||
err = snd_pcm_pause(multi->slaves[i].pcm, enable);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_multi_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info)
|
||||
|
|
@ -408,19 +480,21 @@ static snd_pcm_sframes_t snd_pcm_multi_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
|
|||
snd_pcm_t *slave_i = multi->slaves[i].pcm;
|
||||
snd_pcm_uframes_t f = pos[i] - frames;
|
||||
if (f > 0)
|
||||
snd_pcm_mmap_forward(slave_i, f);
|
||||
snd_pcm_mmap_commit(slave_i, snd_pcm_mmap_offset(slave_i), f);
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_multi_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t snd_pcm_multi_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_multi_t *multi = pcm->private_data;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < multi->slaves_count; ++i) {
|
||||
snd_pcm_t *slave = multi->slaves[i].pcm;
|
||||
snd_pcm_sframes_t frames = snd_pcm_mmap_forward(slave, size);
|
||||
snd_pcm_sframes_t frames = snd_pcm_mmap_commit(slave, offset, size);
|
||||
if (frames < 0)
|
||||
return frames;
|
||||
if (i == 0) {
|
||||
|
|
@ -497,7 +571,7 @@ snd_pcm_fast_ops_t snd_pcm_multi_fast_ops = {
|
|||
readn: snd_pcm_mmap_readn,
|
||||
rewind: snd_pcm_multi_rewind,
|
||||
avail_update: snd_pcm_multi_avail_update,
|
||||
mmap_forward: snd_pcm_multi_mmap_forward,
|
||||
mmap_commit: snd_pcm_multi_mmap_commit,
|
||||
};
|
||||
|
||||
int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
|
||||
|
|
@ -534,8 +608,6 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name,
|
|||
slave->pcm = slaves_pcm[i];
|
||||
slave->channels_count = schannels_count[i];
|
||||
slave->close_slave = close_slaves;
|
||||
if (i != 0)
|
||||
snd_pcm_link(slaves_pcm[i-1], slaves_pcm[i]);
|
||||
}
|
||||
for (i = 0; i < channels_count; ++i) {
|
||||
snd_pcm_multi_channel_t *bind = &multi->channels[i];
|
||||
|
|
|
|||
|
|
@ -219,7 +219,9 @@ static snd_pcm_sframes_t snd_pcm_null_readn(snd_pcm_t *pcm, void **bufs ATTRIBUT
|
|||
return snd_pcm_null_fwd(pcm, size);
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_null_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t snd_pcm_null_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
return snd_pcm_null_fwd(pcm, size);
|
||||
}
|
||||
|
|
@ -316,7 +318,7 @@ snd_pcm_fast_ops_t snd_pcm_null_fast_ops = {
|
|||
readi: snd_pcm_null_readi,
|
||||
readn: snd_pcm_null_readn,
|
||||
avail_update: snd_pcm_null_avail_update,
|
||||
mmap_forward: snd_pcm_null_mmap_forward,
|
||||
mmap_commit: snd_pcm_null_mmap_commit,
|
||||
};
|
||||
|
||||
int snd_pcm_null_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode)
|
||||
|
|
|
|||
|
|
@ -198,29 +198,22 @@ static snd_pcm_uframes_t snd_pcm_plugin_write_areas(snd_pcm_t *pcm,
|
|||
{
|
||||
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||
snd_pcm_t *slave = plugin->slave;
|
||||
const snd_pcm_channel_area_t *slave_areas;
|
||||
snd_pcm_uframes_t slave_offset;
|
||||
snd_pcm_uframes_t xfer = size;
|
||||
slave_areas = snd_pcm_mmap_areas(slave);
|
||||
slave_offset = snd_pcm_mmap_offset(slave);
|
||||
while (size > 0) {
|
||||
snd_pcm_uframes_t frames = size;
|
||||
snd_pcm_uframes_t slave_cont = slave->buffer_size - slave_offset;
|
||||
snd_pcm_uframes_t slave_frames = slave_cont;
|
||||
const snd_pcm_channel_area_t *slave_areas;
|
||||
snd_pcm_uframes_t slave_offset, slave_frames;
|
||||
snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
||||
frames = plugin->write(pcm, areas, offset, frames,
|
||||
slave_areas, slave_offset, &slave_frames);
|
||||
assert(slave_frames <= snd_pcm_mmap_playback_avail(slave));
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
snd_pcm_mmap_hw_forward(pcm, frames);
|
||||
snd_pcm_mmap_forward(slave, slave_frames);
|
||||
snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
snd_atomic_write_end(&plugin->watom);
|
||||
offset += frames;
|
||||
size -= frames;
|
||||
if (slave_frames == slave_cont)
|
||||
slave_offset = 0;
|
||||
else
|
||||
slave_offset += slave_frames;
|
||||
}
|
||||
return xfer;
|
||||
}
|
||||
|
|
@ -232,29 +225,22 @@ static snd_pcm_uframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
|
|||
{
|
||||
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||
snd_pcm_t *slave = plugin->slave;
|
||||
const snd_pcm_channel_area_t *slave_areas;
|
||||
snd_pcm_uframes_t slave_offset;
|
||||
snd_pcm_uframes_t xfer = size;
|
||||
slave_areas = snd_pcm_mmap_areas(slave);
|
||||
slave_offset = snd_pcm_mmap_offset(slave);
|
||||
while (size > 0) {
|
||||
snd_pcm_uframes_t frames = size;
|
||||
snd_pcm_uframes_t slave_cont = slave->buffer_size - slave_offset;
|
||||
snd_pcm_uframes_t slave_frames = slave_cont;
|
||||
const snd_pcm_channel_area_t *slave_areas;
|
||||
snd_pcm_uframes_t slave_offset, slave_frames;
|
||||
snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
||||
frames = plugin->read(pcm, areas, offset, frames,
|
||||
slave_areas, slave_offset, &slave_frames);
|
||||
assert(slave_frames <= snd_pcm_mmap_capture_avail(slave));
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
snd_pcm_mmap_hw_forward(pcm, frames);
|
||||
snd_pcm_mmap_forward(slave, slave_frames);
|
||||
snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
snd_atomic_write_end(&plugin->watom);
|
||||
offset += frames;
|
||||
size -= frames;
|
||||
if (slave_frames == slave_cont)
|
||||
slave_offset = 0;
|
||||
else
|
||||
slave_offset += slave_frames;
|
||||
}
|
||||
return xfer;
|
||||
}
|
||||
|
|
@ -292,13 +278,15 @@ snd_pcm_sframes_t snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_ufra
|
|||
snd_pcm_plugin_read_areas);
|
||||
}
|
||||
|
||||
snd_pcm_sframes_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
snd_pcm_sframes_t snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||
snd_pcm_t *slave = plugin->slave;
|
||||
const snd_pcm_channel_area_t *areas, *slave_areas;
|
||||
snd_pcm_uframes_t xfer, offset;
|
||||
snd_pcm_uframes_t slave_offset, slave_size;
|
||||
const snd_pcm_channel_area_t *areas;
|
||||
snd_pcm_uframes_t xfer, hw_offset;
|
||||
snd_pcm_uframes_t slave_size;
|
||||
if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
snd_pcm_mmap_appl_forward(pcm, size);
|
||||
|
|
@ -309,36 +297,29 @@ snd_pcm_sframes_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t
|
|||
if (slave_size <= 0)
|
||||
return slave_size;
|
||||
areas = snd_pcm_mmap_areas(pcm);
|
||||
offset = snd_pcm_mmap_hw_offset(pcm);
|
||||
slave_areas = snd_pcm_mmap_areas(slave);
|
||||
slave_offset = snd_pcm_mmap_offset(slave);
|
||||
hw_offset = snd_pcm_mmap_hw_offset(pcm);
|
||||
xfer = 0;
|
||||
while (size && slave_size) {
|
||||
snd_pcm_uframes_t frames = size;
|
||||
snd_pcm_uframes_t cont = pcm->buffer_size - offset;
|
||||
snd_pcm_uframes_t slave_frames = slave_size;
|
||||
snd_pcm_uframes_t slave_cont = slave->buffer_size - slave_offset;
|
||||
snd_pcm_uframes_t cont = pcm->buffer_size - hw_offset;
|
||||
const snd_pcm_channel_area_t *slave_areas;
|
||||
snd_pcm_uframes_t slave_offset, slave_frames;
|
||||
snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
||||
if (frames > cont)
|
||||
frames = cont;
|
||||
if (slave_frames > slave_cont)
|
||||
slave_frames = slave_cont;
|
||||
frames = plugin->write(pcm, areas, offset, frames,
|
||||
frames = plugin->write(pcm, areas, hw_offset, frames,
|
||||
slave_areas, slave_offset, &slave_frames);
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
snd_pcm_mmap_appl_forward(pcm, frames);
|
||||
snd_pcm_mmap_hw_forward(pcm, frames);
|
||||
snd_pcm_mmap_forward(slave, slave_frames);
|
||||
snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
snd_atomic_write_end(&plugin->watom);
|
||||
xfer += frames;
|
||||
if (frames == cont)
|
||||
offset = 0;
|
||||
hw_offset = 0;
|
||||
else
|
||||
offset += frames;
|
||||
hw_offset += frames;
|
||||
size -= frames;
|
||||
if (slave_frames == slave_cont)
|
||||
slave_offset = 0;
|
||||
else
|
||||
slave_offset += slave_frames;
|
||||
slave_size -= slave_frames;
|
||||
}
|
||||
return xfer;
|
||||
|
|
@ -348,9 +329,8 @@ snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
|||
{
|
||||
snd_pcm_plugin_t *plugin = pcm->private_data;
|
||||
snd_pcm_t *slave = plugin->slave;
|
||||
const snd_pcm_channel_area_t *areas, *slave_areas;
|
||||
snd_pcm_uframes_t xfer, offset, size;
|
||||
snd_pcm_uframes_t slave_offset;
|
||||
const snd_pcm_channel_area_t *areas;
|
||||
snd_pcm_uframes_t xfer, hw_offset, size;
|
||||
snd_pcm_sframes_t slave_size;
|
||||
slave_size = snd_pcm_avail_update(slave);
|
||||
if (slave_size <= 0)
|
||||
|
|
@ -364,34 +344,27 @@ snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
|
|||
xfer = snd_pcm_mmap_capture_avail(pcm);
|
||||
size = pcm->buffer_size - xfer;
|
||||
areas = snd_pcm_mmap_areas(pcm);
|
||||
offset = snd_pcm_mmap_hw_offset(pcm);
|
||||
slave_areas = snd_pcm_mmap_areas(slave);
|
||||
slave_offset = snd_pcm_mmap_offset(slave);
|
||||
hw_offset = snd_pcm_mmap_hw_offset(pcm);
|
||||
while (size && slave_size) {
|
||||
snd_pcm_uframes_t frames = size;
|
||||
snd_pcm_uframes_t cont = pcm->buffer_size - offset;
|
||||
snd_pcm_uframes_t slave_frames = slave_size;
|
||||
snd_pcm_uframes_t slave_cont = slave->buffer_size - slave_offset;
|
||||
snd_pcm_uframes_t cont = pcm->buffer_size - hw_offset;
|
||||
const snd_pcm_channel_area_t *slave_areas;
|
||||
snd_pcm_uframes_t slave_offset, slave_frames;
|
||||
snd_pcm_mmap_begin(slave, &slave_areas, &slave_offset, &slave_frames);
|
||||
if (frames > cont)
|
||||
frames = cont;
|
||||
if (slave_frames > slave_cont)
|
||||
slave_frames = slave_cont;
|
||||
frames = plugin->read(pcm, areas, offset, frames,
|
||||
frames = plugin->read(pcm, areas, hw_offset, frames,
|
||||
slave_areas, slave_offset, &slave_frames);
|
||||
snd_atomic_write_begin(&plugin->watom);
|
||||
snd_pcm_mmap_hw_forward(pcm, frames);
|
||||
snd_pcm_mmap_forward(slave, slave_frames);
|
||||
snd_pcm_mmap_commit(slave, slave_offset, slave_frames);
|
||||
snd_atomic_write_end(&plugin->watom);
|
||||
xfer += frames;
|
||||
if (frames == cont)
|
||||
offset = 0;
|
||||
hw_offset = 0;
|
||||
else
|
||||
offset += frames;
|
||||
hw_offset += frames;
|
||||
size -= frames;
|
||||
if (slave_frames == slave_cont)
|
||||
slave_offset = 0;
|
||||
else
|
||||
slave_offset += slave_frames;
|
||||
slave_size -= slave_frames;
|
||||
}
|
||||
return xfer;
|
||||
|
|
@ -474,6 +447,6 @@ snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops = {
|
|||
readi: snd_pcm_plugin_readi,
|
||||
readn: snd_pcm_plugin_readn,
|
||||
avail_update: snd_pcm_plugin_avail_update,
|
||||
mmap_forward: snd_pcm_plugin_mmap_forward,
|
||||
mmap_commit: snd_pcm_plugin_mmap_commit,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ snd_pcm_sframes_t snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_
|
|||
snd_pcm_sframes_t snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_plugin_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size);
|
||||
snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm);
|
||||
int snd_pcm_plugin_mmap_status(snd_pcm_t *pcm);
|
||||
int snd_pcm_plugin_mmap_control(snd_pcm_t *pcm);
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ static snd_pcm_uframes_t snd_pcm_share_slave_avail(snd_pcm_share_slave_t *slave)
|
|||
}
|
||||
|
||||
/* Warning: take the mutex before to call this */
|
||||
/* Return number of frames to mmap_forward the slave */
|
||||
/* Return number of frames to mmap_commit the slave */
|
||||
static snd_pcm_uframes_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave)
|
||||
{
|
||||
struct list_head *i;
|
||||
|
|
@ -223,7 +223,7 @@ static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm, int slave_xrun)
|
|||
frames = -safety_missing;
|
||||
missing = 1;
|
||||
}
|
||||
err = snd_pcm_mmap_forward(spcm, frames);
|
||||
err = snd_pcm_mmap_commit(spcm, snd_pcm_mmap_offset(spcm), frames);
|
||||
assert(err == frames);
|
||||
slave_avail -= frames;
|
||||
} else {
|
||||
|
|
@ -756,22 +756,25 @@ static snd_pcm_sframes_t snd_pcm_share_avail_update(snd_pcm_t *pcm)
|
|||
}
|
||||
|
||||
/* Call it with mutex held */
|
||||
static snd_pcm_sframes_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t _snd_pcm_share_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_share_t *share = pcm->private_data;
|
||||
snd_pcm_share_slave_t *slave = share->slave;
|
||||
snd_pcm_t *spcm = slave->pcm;
|
||||
snd_pcm_sframes_t ret = 0;
|
||||
snd_pcm_sframes_t frames;
|
||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK &&
|
||||
share->state == SND_PCM_STATE_RUNNING) {
|
||||
frames = *slave->pcm->appl_ptr - share->appl_ptr;
|
||||
frames = *spcm->appl_ptr - share->appl_ptr;
|
||||
if (frames > (snd_pcm_sframes_t)pcm->buffer_size)
|
||||
frames -= pcm->boundary;
|
||||
else if (frames < -(snd_pcm_sframes_t)pcm->buffer_size)
|
||||
frames += pcm->boundary;
|
||||
if (frames > 0) {
|
||||
/* Latecomer PCM */
|
||||
ret = snd_pcm_rewind(slave->pcm, frames);
|
||||
ret = snd_pcm_rewind(spcm, frames);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -781,7 +784,7 @@ static snd_pcm_sframes_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, snd_pcm_ufr
|
|||
frames = _snd_pcm_share_slave_forward(slave);
|
||||
if (frames > 0) {
|
||||
snd_pcm_sframes_t err;
|
||||
err = snd_pcm_mmap_forward(slave->pcm, frames);
|
||||
err = snd_pcm_mmap_commit(spcm, snd_pcm_mmap_offset(spcm), frames);
|
||||
assert(err == frames);
|
||||
}
|
||||
_snd_pcm_share_update(pcm);
|
||||
|
|
@ -789,13 +792,15 @@ static snd_pcm_sframes_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, snd_pcm_ufr
|
|||
return size;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_share_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t snd_pcm_share_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_share_t *share = pcm->private_data;
|
||||
snd_pcm_share_slave_t *slave = share->slave;
|
||||
snd_pcm_sframes_t ret;
|
||||
Pthread_mutex_lock(&slave->mutex);
|
||||
ret = _snd_pcm_share_mmap_forward(pcm, size);
|
||||
ret = _snd_pcm_share_mmap_commit(pcm, offset, size);
|
||||
Pthread_mutex_unlock(&slave->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -838,6 +843,7 @@ static int snd_pcm_share_start(snd_pcm_t *pcm)
|
|||
{
|
||||
snd_pcm_share_t *share = pcm->private_data;
|
||||
snd_pcm_share_slave_t *slave = share->slave;
|
||||
snd_pcm_t *spcm = slave->pcm;
|
||||
int err = 0;
|
||||
if (share->state != SND_PCM_STATE_PREPARED)
|
||||
return -EBADFD;
|
||||
|
|
@ -852,16 +858,16 @@ static int snd_pcm_share_start(snd_pcm_t *pcm)
|
|||
}
|
||||
if (slave->running_count) {
|
||||
snd_pcm_sframes_t sd;
|
||||
err = snd_pcm_delay(slave->pcm, &sd);
|
||||
err = snd_pcm_delay(spcm, &sd);
|
||||
if (err < 0)
|
||||
goto _end;
|
||||
err = snd_pcm_rewind(slave->pcm, sd);
|
||||
err = snd_pcm_rewind(spcm, sd);
|
||||
if (err < 0)
|
||||
goto _end;
|
||||
}
|
||||
assert(share->hw_ptr == 0);
|
||||
share->hw_ptr = *slave->pcm->hw_ptr;
|
||||
share->appl_ptr = *slave->pcm->appl_ptr;
|
||||
share->hw_ptr = *spcm->hw_ptr;
|
||||
share->appl_ptr = *spcm->appl_ptr;
|
||||
while (xfer < hw_avail) {
|
||||
snd_pcm_uframes_t frames = hw_avail - xfer;
|
||||
snd_pcm_uframes_t offset = snd_pcm_mmap_offset(pcm);
|
||||
|
|
@ -877,10 +883,10 @@ static int snd_pcm_share_start(snd_pcm_t *pcm)
|
|||
}
|
||||
snd_pcm_mmap_appl_forward(pcm, hw_avail);
|
||||
if (slave->running_count == 0)
|
||||
snd_pcm_mmap_forward(slave->pcm, hw_avail);
|
||||
snd_pcm_mmap_commit(spcm, snd_pcm_mmap_offset(spcm), hw_avail);
|
||||
}
|
||||
if (slave->running_count == 0) {
|
||||
err = snd_pcm_start(slave->pcm);
|
||||
err = snd_pcm_start(spcm);
|
||||
if (err < 0)
|
||||
goto _end;
|
||||
}
|
||||
|
|
@ -1181,7 +1187,7 @@ snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
|
|||
readn: snd_pcm_mmap_readn,
|
||||
rewind: snd_pcm_share_rewind,
|
||||
avail_update: snd_pcm_share_avail_update,
|
||||
mmap_forward: snd_pcm_share_mmap_forward,
|
||||
mmap_commit: snd_pcm_share_mmap_commit,
|
||||
};
|
||||
|
||||
int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
|
||||
|
|
|
|||
|
|
@ -435,12 +435,15 @@ static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t fr
|
|||
return snd_pcm_shm_action(pcm);
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_shm_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t snd_pcm_shm_mmap_commit(snd_pcm_t *pcm,
|
||||
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
||||
snd_pcm_uframes_t size)
|
||||
{
|
||||
snd_pcm_shm_t *shm = pcm->private_data;
|
||||
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
|
||||
ctrl->cmd = SND_PCM_IOCTL_MMAP_FORWARD;
|
||||
ctrl->u.mmap_forward.frames = size;
|
||||
ctrl->cmd = SND_PCM_IOCTL_MMAP_COMMIT;
|
||||
ctrl->u.mmap_commit.offset = offset;
|
||||
ctrl->u.mmap_commit.frames = size;
|
||||
return snd_pcm_shm_action(pcm);
|
||||
}
|
||||
|
||||
|
|
@ -510,7 +513,7 @@ snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
|
|||
readi: snd_pcm_mmap_readi,
|
||||
readn: snd_pcm_mmap_readn,
|
||||
avail_update: snd_pcm_shm_avail_update,
|
||||
mmap_forward: snd_pcm_shm_mmap_forward,
|
||||
mmap_commit: snd_pcm_shm_mmap_commit,
|
||||
};
|
||||
|
||||
static int make_local_socket(const char *filename)
|
||||
|
|
|
|||
|
|
@ -207,13 +207,13 @@ static snd_pcm_sframes_t snd_pcm_surround_readn(snd_pcm_t *pcm, void **bufs, snd
|
|||
return res;
|
||||
}
|
||||
|
||||
static snd_pcm_sframes_t snd_pcm_surround_mmap_forward(snd_pcm_t *pcm, snd_pcm_uframes_t size)
|
||||
static snd_pcm_sframes_t snd_pcm_surround_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size)
|
||||
{
|
||||
int i;
|
||||
snd_pcm_sframes_t res = -1, res1;
|
||||
snd_pcm_surround_t *surr = pcm->private_data;
|
||||
for (i = 0; i < surr->pcms; i++) {
|
||||
res1 = snd_pcm_mmap_forward(surr->pcm[i], size);
|
||||
res1 = snd_pcm_mmap_commit(surr->pcm[i], offset, size);
|
||||
if (res1 < 0)
|
||||
return res1;
|
||||
if (res < 0) {
|
||||
|
|
@ -367,7 +367,7 @@ snd_pcm_fast_ops_t snd_pcm_surround_fast_ops = {
|
|||
readi: snd_pcm_surround_readi,
|
||||
readn: snd_pcm_surround_readn,
|
||||
avail_update: snd_pcm_surround_avail_update,
|
||||
mmap_forward: snd_pcm_surround_mmap_forward,
|
||||
mmap_commit: snd_pcm_surround_mmap_commit,
|
||||
};
|
||||
|
||||
int snd_pcm_surround_open(snd_pcm_t **pcmp, const char *name, int card, int dev,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue