mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Improved mmap emulation over write/read
This commit is contained in:
parent
437c96ef5f
commit
484c05ec36
1 changed files with 44 additions and 11 deletions
|
|
@ -45,12 +45,19 @@ typedef struct {
|
||||||
int card, device, subdevice;
|
int card, device, subdevice;
|
||||||
volatile struct sndrv_pcm_mmap_status *mmap_status;
|
volatile struct sndrv_pcm_mmap_status *mmap_status;
|
||||||
struct sndrv_pcm_mmap_control *mmap_control;
|
struct sndrv_pcm_mmap_control *mmap_control;
|
||||||
|
int shadow_appl_ptr: 1, avail_update_flag: 1;
|
||||||
|
snd_pcm_uframes_t appl_ptr;
|
||||||
int shmid;
|
int shmid;
|
||||||
} snd_pcm_hw_t;
|
} snd_pcm_hw_t;
|
||||||
|
|
||||||
#define SNDRV_FILE_PCM_STREAM_PLAYBACK "/dev/snd/pcmC%iD%ip"
|
#define SNDRV_FILE_PCM_STREAM_PLAYBACK "/dev/snd/pcmC%iD%ip"
|
||||||
#define SNDRV_FILE_PCM_STREAM_CAPTURE "/dev/snd/pcmC%iD%ic"
|
#define SNDRV_FILE_PCM_STREAM_CAPTURE "/dev/snd/pcmC%iD%ic"
|
||||||
#define SNDRV_PCM_VERSION_MAX SNDRV_PROTOCOL_VERSION(2, 0, 0)
|
#define SNDRV_PCM_VERSION_MAX SNDRV_PROTOCOL_VERSION(2, 0, 0)
|
||||||
|
|
||||||
|
/* update appl_ptr with driver */
|
||||||
|
#define UPDATE_SHADOW_PTR(hw) \
|
||||||
|
do { if (hw->shadow_appl_ptr && !hw->avail_update_flag) \
|
||||||
|
hw->appl_ptr = hw->mmap_control->appl_ptr; } while (0)
|
||||||
|
|
||||||
static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
|
static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
|
||||||
{
|
{
|
||||||
|
|
@ -134,6 +141,16 @@ static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
||||||
SYSERR("SNDRV_PCM_IOCTL_HW_PARAMS failed");
|
SYSERR("SNDRV_PCM_IOCTL_HW_PARAMS failed");
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
|
||||||
|
if (!(params->info & SNDRV_PCM_INFO_MMAP)) {
|
||||||
|
hw->shadow_appl_ptr = 1;
|
||||||
|
hw->appl_ptr = 0;
|
||||||
|
pcm->appl_ptr = &hw->appl_ptr;
|
||||||
|
} else {
|
||||||
|
hw->shadow_appl_ptr = 0;
|
||||||
|
pcm->appl_ptr = &hw->mmap_control->appl_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -358,6 +375,7 @@ static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_
|
||||||
result = ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi);
|
result = ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
UPDATE_SHADOW_PTR(hw);
|
||||||
return xferi.result;
|
return xferi.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -372,6 +390,7 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u
|
||||||
result = ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern);
|
result = ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
UPDATE_SHADOW_PTR(hw);
|
||||||
return xfern.result;
|
return xfern.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -467,28 +486,42 @@ static int snd_pcm_hw_close(snd_pcm_t *pcm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
|
static int snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
|
||||||
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
|
||||||
snd_pcm_uframes_t size)
|
snd_pcm_uframes_t size)
|
||||||
{
|
{
|
||||||
if (!(pcm->info & SND_PCM_INFO_MMAP) &&
|
if (!(pcm->info & SND_PCM_INFO_MMAP)) {
|
||||||
pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
return snd_pcm_write_mmap(pcm, size);
|
snd_pcm_sframes_t res;
|
||||||
|
do {
|
||||||
|
res = snd_pcm_write_mmap(pcm, size);
|
||||||
|
if (res < 0)
|
||||||
|
return res;
|
||||||
|
size -= res;
|
||||||
|
} while (size > 0);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
snd_pcm_hw_t *hw = pcm->private_data;
|
||||||
|
assert(hw->shadow_appl_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
snd_pcm_mmap_appl_forward(pcm, size);
|
snd_pcm_mmap_appl_forward(pcm, size);
|
||||||
return size;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
|
static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_uframes_t avail;
|
snd_pcm_uframes_t avail;
|
||||||
snd_pcm_sframes_t err;
|
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
avail = snd_pcm_mmap_playback_avail(pcm);
|
avail = snd_pcm_mmap_playback_avail(pcm);
|
||||||
} else {
|
} else {
|
||||||
avail = snd_pcm_mmap_capture_avail(pcm);
|
avail = snd_pcm_mmap_capture_avail(pcm);
|
||||||
if (avail > 0 &&
|
if (avail > 0 && !(pcm->info & SND_PCM_INFO_MMAP)) {
|
||||||
!(pcm->info & SND_PCM_INFO_MMAP)) {
|
snd_pcm_sframes_t err;
|
||||||
|
snd_pcm_hw_t *hw = pcm->private_data;
|
||||||
|
hw->avail_update_flag = 1;
|
||||||
err = snd_pcm_read_mmap(pcm, avail);
|
err = snd_pcm_read_mmap(pcm, avail);
|
||||||
|
hw->avail_update_flag = 0;
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
assert((snd_pcm_uframes_t)err == avail);
|
assert((snd_pcm_uframes_t)err == avail);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue