@@ -973,6 +973,7 @@ int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
__snd_pcm_unlock(pcm);
return err;
}
+ pcm->original_avail_min = pcm->avail_min;
__snd_pcm_unlock(pcm);
return 0;
}
@@ -7267,6 +7268,17 @@ void snd_pcm_areas_from_bufs(snd_pcm_t *pcm, snd_pcm_channel_area_t *areas,
snd_pcm_unlock(pcm);
}
+static void snd_pcm_set_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail)
+{
+ if (avail != pcm->avail_min) {
+ snd_pcm_sw_params_t swparams;
+
+ snd_pcm_sw_params_current(pcm, &swparams);
+ swparams.avail_min = avail;
+ _snd_pcm_sw_params_internal(pcm, &swparams);
+ }
+}
+
snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset, snd_pcm_uframes_t size,
snd_pcm_xfer_areas_func_t func)
@@ -7274,6 +7286,7 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
snd_pcm_uframes_t xfer = 0;
snd_pcm_sframes_t err = 0;
snd_pcm_state_t state;
+ snd_pcm_uframes_t needed_slave_avail_min = 0;
if (size == 0)
return 0;
@@ -7332,6 +7345,14 @@ snd_pcm_sframes_t snd_pcm_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_
if (err < 0)
break;
frames = err;
+ pcm->unaligned_frames += frames;
+ pcm->unaligned_frames %= pcm->period_size;
+ if (pcm->unaligned_frames) {
+ needed_slave_avail_min = pcm->period_size - pcm->unaligned_frames;
+ snd_pcm_set_avail_min(pcm, needed_slave_avail_min);
+ } else {
+ snd_pcm_set_avail_min(pcm, pcm->original_avail_min);
+ }
offset += frames;
size -= frames;
xfer += frames;
@@ -210,6 +210,8 @@ struct _snd_pcm {
snd_pcm_tstamp_type_t tstamp_type; /* timestamp type */
unsigned int period_step;
snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
+ snd_pcm_uframes_t unaligned_frames;
+ snd_pcm_uframes_t original_avail_min;
int period_event;
snd_pcm_uframes_t start_threshold;
snd_pcm_uframes_t stop_threshold;