[alsa-devel] More snd_pcm_ioplug_avail_update() questions

Takashi Iwai tiwai at suse.de
Tue Jul 31 10:21:37 CEST 2018


On Mon, 30 Jul 2018 20:55:45 +0200,
Rob Duncan wrote:
> 
> At 08:14 on Thu, Jul 26 2018, Takashi wrote:
> 
> > Maybe we can track the own applptr (e.g. transfer_ptr or such) and
> > calculate the transfer size from it instead of snd_pcm_mmap_begin();
> > i.e. write some open codes of alternative snd_pcm_mmap_begin() there.
> >
> > Then transfer_ptr is updated again in snd_pcm_ioplug_mmap_commit() as
> > well when applptr is updated.
> >
> > Of course, there is a smarter way, I'd happily take another approach.
> 
> Thanks for the hint.  I'm not sure I 100% understand your suggestion,
> though.

Well, something like below (totally untested).


Takashi

---
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -44,6 +44,7 @@ typedef struct snd_pcm_ioplug_priv {
 	struct snd_ext_parm params[SND_PCM_IOPLUG_HW_PARAMS];
 	snd_pcm_uframes_t last_hw;
 	snd_pcm_uframes_t avail_max;
+	snd_pcm_uframes_t transfer_offset;
 	snd_htimestamp_t trigger_tstamp;
 } ioplug_priv_t;
 
@@ -154,6 +155,7 @@ static int snd_pcm_ioplug_reset(snd_pcm_t *pcm)
 	io->data->hw_ptr = 0;
 	io->last_hw = 0;
 	io->avail_max = 0;
+	io->transfer_offset = 0;
 	return 0;
 }
 
@@ -595,7 +597,10 @@ static snd_pcm_sframes_t snd_pcm_ioplug_rewindable(snd_pcm_t *pcm)
 
 static snd_pcm_sframes_t snd_pcm_ioplug_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
+	ioplug_priv_t *io = pcm->private_data;
+
 	snd_pcm_mmap_appl_backward(pcm, frames);
+	io->transfer_offset = io->data->appl_ptr;
 	return frames;
 }
 
@@ -606,7 +611,10 @@ static snd_pcm_sframes_t snd_pcm_ioplug_forwardable(snd_pcm_t *pcm)
 
 static snd_pcm_sframes_t snd_pcm_ioplug_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
+	ioplug_priv_t *io = pcm->private_data;
+
 	snd_pcm_mmap_appl_forward(pcm, frames);
+	io->transfer_offset = io->data->appl_ptr;
 	return frames;
 }
 
@@ -723,10 +731,16 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
 	    pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
 		if (io->data->callback->transfer) {
 			const snd_pcm_channel_area_t *areas;
-			snd_pcm_uframes_t offset, size = UINT_MAX;
+			snd_pcm_uframes_t offset, size;
 			snd_pcm_sframes_t result;
 
-			__snd_pcm_mmap_begin(pcm, &areas, &offset, &size);
+			areas = snd_pcm_mmap_areas(pcm);
+			if (!areas)
+				return -EBADFD;
+			offset = io->transfer_offset;
+			size = pcm->buffer_size - offset;
+			if (avail < size)
+				size = avail;
 			result = io->data->callback->transfer(io->data, areas, offset, size);
 			if (result < 0)
 				return result;
@@ -741,6 +755,9 @@ static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm)
 				if (result < 0)
 					return result;
 			}
+
+			io->transfer_offset += avail;
+			io->transfer_offset %= pcm->buffer_size;
 		}
 	}
 	if (avail > io->avail_max)


More information about the Alsa-devel mailing list