@@ -40,6 +40,7 @@ typedef struct {
char **port_names;
unsigned int num_ports;
+ snd_pcm_uframes_t boundary;
unsigned int hw_ptr;
unsigned int sample_bits;
snd_pcm_uframes_t min_avail;
@@ -130,6 +131,21 @@ static int snd_pcm_jack_poll_revents(snd_pcm_ioplug_t *io,
static snd_pcm_sframes_t snd_pcm_jack_pointer(snd_pcm_ioplug_t *io)
{
snd_pcm_jack_t *jack = io->private_data;
+
+ /* ALSA library is calulating the delta between the last pointer and
+ * the current one.
+ * Normally it is expecting a value between 0 and buffer_size.
+ * The following example would result in an negative delta
+ * which would result in a hw_ptr which will be reduced.
+ * last_hw = jack->boundary - io->buffer_size
+ * hw = 0
+ * But we cannot use
+ * return jack->hw_ptr % io->buffer_size;
+ * because in this case an update of
+ * hw_ptr += io->buffer_size
+ * would not be recognized by the ALSA library.
+ * Therefore we are using jack->boundary as the wrap around.
+ */
return jack->hw_ptr;
}
@@ -162,7 +178,7 @@ snd_pcm_jack_process_cb(jack_nframes_t nframes, snd_pcm_ioplug_t *io)
while (xfer < nframes) {
snd_pcm_uframes_t frames = nframes - xfer;
- snd_pcm_uframes_t offset = hw_ptr;
+ snd_pcm_uframes_t offset = hw_ptr % io->buffer_size;
snd_pcm_uframes_t cont = io->buffer_size - offset;
if (cont < frames)
@@ -176,7 +192,8 @@ snd_pcm_jack_process_cb(jack_nframes_t nframes, snd_pcm_ioplug_t *io)
}
hw_ptr += frames;
- hw_ptr %= io->buffer_size;
+ if (hw_ptr >= jack->boundary)
+ hw_ptr -= jack->boundary;
xfer += frames;
}
jack->hw_ptr = hw_ptr;
@@ -200,6 +217,8 @@ static int snd_pcm_jack_prepare(snd_pcm_ioplug_t *io)
err = snd_pcm_sw_params_current(io->pcm, swparams);
if (err == 0) {
snd_pcm_sw_params_get_avail_min(swparams, &jack->min_avail);
+ /* get boundary for available calulation */
+ snd_pcm_sw_params_get_boundary(swparams, &jack->boundary);
}
/* deactivate jack connections if this is XRUN recovery */