]> git.alsa-project.org Git - alsa-lib.git/commitdiff
pcm: Fix forward/rewind support in iec958 plugin
authorAlexander E. Patrakov <patrakov@gmail.com>
Thu, 24 Apr 2014 14:40:06 +0000 (20:40 +0600)
committerTakashi Iwai <tiwai@suse.de>
Mon, 28 Apr 2014 16:09:56 +0000 (18:09 +0200)
When forwarding or rewinding, the frame counter was not updated. This
could result in corrupted channel status words or misplaced Z-type
preamble.

Signed-off-by: Alexander E. Patrakov <patrakov@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
src/pcm/pcm_iec958.c
src/pcm/pcm_plugin.c
src/pcm/pcm_plugin.h

index d81b0a142be12798e2a478831a405fd59eaa4eac..0c61fc17995b6578cdf52c1280f42c2b219a370e 100644 (file)
@@ -62,6 +62,7 @@ struct snd_pcm_iec958 {
        unsigned char status[24];
        unsigned int byteswap;
        unsigned char preamble[3];      /* B/M/W or Z/X/Y */
+       snd_pcm_fast_ops_t fops;
 };
 
 enum { PREAMBLE_Z, PREAMBLE_X, PREAMBLE_Y };
@@ -416,6 +417,35 @@ static void snd_pcm_iec958_dump(snd_pcm_t *pcm, snd_output_t *out)
        snd_pcm_dump(iec->plug.gen.slave, out);
 }
 
+static snd_pcm_sframes_t snd_pcm_iec958_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+       unsigned int counter_decrement;
+       snd_pcm_iec958_t *iec = pcm->private_data;
+       snd_pcm_sframes_t result = snd_pcm_plugin_rewind(pcm, frames);
+       if (result <= 0)
+               return result;
+
+       counter_decrement = result % 192;
+       iec->counter += 192 - counter_decrement;
+       iec->counter %= 192;
+       return result;
+}
+
+static snd_pcm_sframes_t snd_pcm_iec958_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
+
+{
+       unsigned int counter_increment;
+       snd_pcm_iec958_t *iec = pcm->private_data;
+       snd_pcm_sframes_t result = snd_pcm_plugin_rewind(pcm, frames);
+       if (result <= 0)
+               return result;
+
+       counter_increment = result % 192;
+       iec->counter += counter_increment;
+       iec->counter %= 192;
+       return result;
+}
+
 static const snd_pcm_ops_t snd_pcm_iec958_ops = {
        .close = snd_pcm_generic_close,
        .info = snd_pcm_generic_info,
@@ -495,7 +525,12 @@ int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
                return err;
        }
        pcm->ops = &snd_pcm_iec958_ops;
-       pcm->fast_ops = &snd_pcm_plugin_fast_ops;
+
+       iec->fops = snd_pcm_plugin_fast_ops;
+       iec->fops.rewind = snd_pcm_iec958_rewind;
+       iec->fops.forward = snd_pcm_iec958_forward;
+       pcm->fast_ops = &iec->fops;
+
        pcm->private_data = iec;
        pcm->poll_fd = slave->poll_fd;
        pcm->poll_events = slave->poll_events;
index 17157e8763fa3612928fa04865fedb41bf089a9a..4ddf10c1989e4918325472976b85179fd503d7f9 100644 (file)
@@ -201,7 +201,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm)
        return snd_pcm_mmap_hw_avail(pcm);
 }
 
-static snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
+snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_plugin_t *plugin = pcm->private_data;
        snd_pcm_sframes_t n = snd_pcm_mmap_hw_avail(pcm);
@@ -229,7 +229,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm)
        return snd_pcm_mmap_avail(pcm);
 }
 
-static snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
+snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
 {
        snd_pcm_plugin_t *plugin = pcm->private_data;
        snd_pcm_sframes_t n = snd_pcm_mmap_avail(pcm);
index 7ee7c7f78df9147683c114e4a2df2a022f4b165f..19e82c3e7321b1ef01dc1f80800fd7ff63844543 100644 (file)
@@ -58,8 +58,14 @@ typedef struct {
        snd1_pcm_plugin_undo_read_generic
 #define snd_pcm_plugin_undo_write_generic \
        snd1_pcm_plugin_undo_write_generic
+#define snd_pcm_plugin_rewind \
+       snd1_pcm_plugin_rewind
+#define snd_pcm_plugin_forward \
+       snd1_pcm_plugin_forward
 
 void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin);
+snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
 
 extern const snd_pcm_fast_ops_t snd_pcm_plugin_fast_ops;