Alsa-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Fix forward/rewind support in iec958 plugin
@ 2014-04-23 18:40 Alexander E. Patrakov
  2014-04-24 11:19 ` David Henningsson
  0 siblings, 1 reply; 7+ messages in thread
From: Alexander E. Patrakov @ 2014-04-23 18:40 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Alexander E. Patrakov

When forwarding or rewinding, the frame counter was not updated. This
could result in corrupted channel status words or misplaced Z-type
preamble.
---
I found the issue by inspecting the code. However, I have no hardware
to test this fix on.

 src/pcm/pcm_iec958.c | 64 +++++++++++++++++++++++++++++++++++++++++++++-
 src/pcm/pcm_plugin.c | 28 ++++++++++----------
 src/pcm/pcm_plugin.h | 72 +++++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 145 insertions(+), 19 deletions(-)

diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c
index d81b0a1..facf683 100644
--- a/src/pcm/pcm_iec958.c
+++ b/src/pcm/pcm_iec958.c
@@ -416,6 +416,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,
@@ -434,6 +463,39 @@ static const snd_pcm_ops_t snd_pcm_iec958_ops = {
 	.set_chmap = snd_pcm_generic_set_chmap,
 };
 
+
+static const snd_pcm_fast_ops_t snd_pcm_iec958_fast_ops = {
+	.status = snd_pcm_plugin_status,
+	.state = snd_pcm_generic_state,
+	.hwsync = snd_pcm_generic_hwsync,
+	.delay = snd_pcm_plugin_delay,
+	.prepare = snd_pcm_plugin_prepare,
+	.reset = snd_pcm_plugin_reset,
+	.start = snd_pcm_generic_start,
+	.drop = snd_pcm_generic_drop,
+	.drain = snd_pcm_generic_drain,
+	.pause = snd_pcm_generic_pause,
+	.rewindable = snd_pcm_plugin_rewindable,
+	.rewind = snd_pcm_iec958_rewind,
+	.forwardable = snd_pcm_plugin_forwardable,
+	.forward = snd_pcm_iec958_forward,
+	.resume = snd_pcm_generic_resume,
+	.link = snd_pcm_generic_link,
+	.link_slaves = snd_pcm_generic_link_slaves,
+	.unlink = snd_pcm_generic_unlink,
+	.writei = snd_pcm_plugin_writei,
+	.writen = snd_pcm_plugin_writen,
+	.readi = snd_pcm_plugin_readi,
+	.readn = snd_pcm_plugin_readn,
+	.avail_update = snd_pcm_plugin_avail_update,
+	.mmap_commit = snd_pcm_plugin_mmap_commit,
+	.htimestamp = snd_pcm_generic_htimestamp,
+	.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
+	.poll_descriptors = snd_pcm_generic_poll_descriptors,
+	.poll_revents = snd_pcm_generic_poll_revents,
+	.may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
+};
+
 /**
  * \brief Creates a new IEC958 subframe conversion PCM
  * \param pcmp Returns created PCM handle
@@ -495,7 +557,7 @@ 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;
+	pcm->fast_ops = &snd_pcm_iec958_fast_ops;
 	pcm->private_data = iec;
 	pcm->poll_fd = slave->poll_fd;
 	pcm->poll_events = slave->poll_events;
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 17157e8..022d908 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -137,7 +137,7 @@ void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin)
 	snd_atomic_write_init(&plugin->watom);
 }
 
-static int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
+int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 {
 	snd_pcm_plugin_t *plugin = pcm->private_data;
 	snd_pcm_sframes_t sd;
@@ -154,7 +154,7 @@ static int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
 	return 0;
 }
 
-static int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
+int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
 {
 	snd_pcm_plugin_t *plugin = pcm->private_data;
 	int err;
@@ -175,7 +175,7 @@ static int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
 	return 0;
 }
 
-static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
+int snd_pcm_plugin_reset(snd_pcm_t *pcm)
 {
 	snd_pcm_plugin_t *plugin = pcm->private_data;
 	int err;
@@ -196,12 +196,12 @@ static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
 	return 0;
 }
 
-static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm)
+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);
@@ -224,12 +224,12 @@ static snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
 	return (snd_pcm_sframes_t) sframes;
 }
 
-static snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm)
+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);
@@ -347,7 +347,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
 }
 
 
-static snd_pcm_sframes_t
+snd_pcm_sframes_t
 snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
 {
 	snd_pcm_channel_area_t areas[pcm->channels];
@@ -356,7 +356,7 @@ snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size
 				   snd_pcm_plugin_write_areas);
 }
 
-static snd_pcm_sframes_t
+snd_pcm_sframes_t
 snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
 {
 	snd_pcm_channel_area_t areas[pcm->channels];
@@ -365,7 +365,7 @@ snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
 				   snd_pcm_plugin_write_areas);
 }
 
-static snd_pcm_sframes_t
+snd_pcm_sframes_t
 snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
 {
 	snd_pcm_channel_area_t areas[pcm->channels];
@@ -374,7 +374,7 @@ snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
 				  snd_pcm_plugin_read_areas);
 }
 
-static snd_pcm_sframes_t
+snd_pcm_sframes_t
 snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
 {
 	snd_pcm_channel_area_t areas[pcm->channels];
@@ -383,7 +383,7 @@ snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
 				  snd_pcm_plugin_read_areas);
 }
 
-static snd_pcm_sframes_t
+snd_pcm_sframes_t
 snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
 			   snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
 			   snd_pcm_uframes_t size)
@@ -452,7 +452,7 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
 	return xfer;
 }
 
-static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
+snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
 {
 	snd_pcm_plugin_t *plugin = pcm->private_data;
 	snd_pcm_t *slave = plugin->gen.slave;
@@ -516,7 +516,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
 	}
 }
 
-static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
+int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
 {
 	snd_pcm_plugin_t *plugin = pcm->private_data;
 	snd_pcm_sframes_t err;
diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h
index 7ee7c7f..7734369 100644
--- a/src/pcm/pcm_plugin.h
+++ b/src/pcm/pcm_plugin.h
@@ -50,14 +50,42 @@ typedef struct {
 } snd_pcm_plugin_t;	
 
 /* make local functions really local */
-#define snd_pcm_plugin_init \
-	snd1_pcm_plugin_init
-#define snd_pcm_plugin_fast_ops \
-	snd1_pcm_plugin_fast_ops
 #define snd_pcm_plugin_undo_read_generic \
 	snd1_pcm_plugin_undo_read_generic
 #define snd_pcm_plugin_undo_write_generic \
 	snd1_pcm_plugin_undo_write_generic
+#define snd_pcm_plugin_init \
+	snd1_pcm_plugin_init
+#define snd_pcm_plugin_delay \
+	snd1_pcm_plugin_delay
+#define snd_pcm_plugin_prepare \
+	snd1_pcm_plugin_prepare
+#define snd_pcm_plugin_reset \
+	snd1_pcm_plugin_reset
+#define snd_pcm_plugin_rewindable \
+	snd1_pcm_plugin_rewindable
+#define snd_pcm_plugin_rewind \
+	snd1_pcm_plugin_rewind
+#define snd_pcm_plugin_forwardable \
+	snd1_pcm_plugin_forwardable
+#define snd_pcm_plugin_forward \
+	snd1_pcm_plugin_forward
+#define snd_pcm_plugin_writei \
+	snd1_pcm_plugin_writei
+#define snd_pcm_plugin_writen \
+	snd1_pcm_plugin_writen
+#define snd_pcm_plugin_readi \
+	snd1_pcm_plugin_readi
+#define snd_pcm_plugin_readn \
+	snd1_pcm_plugin_readn
+#define snd_pcm_plugin_mmap_commit \
+	snd1_pcm_plugin_mmap_commit
+#define snd_pcm_plugin_avail_update \
+	snd1_pcm_plugin_avail_update
+#define snd_pcm_plugin_status \
+	snd1_pcm_plugin_status
+#define snd_pcm_plugin_fast_ops \
+	snd1_pcm_plugin_fast_ops
 
 void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin);
 
@@ -77,6 +105,42 @@ snd_pcm_sframes_t snd_pcm_plugin_undo_write_generic
       snd_pcm_uframes_t res_size,		/* size of result areas */
       snd_pcm_uframes_t slave_undo_size);
 
+int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
+int snd_pcm_plugin_prepare(snd_pcm_t *pcm);
+int snd_pcm_plugin_reset(snd_pcm_t *pcm);
+snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm);
+snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm);
+snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+
+snd_pcm_sframes_t snd_pcm_plugin_writei
+      (snd_pcm_t *pcm,
+       const void *buffer,
+       snd_pcm_uframes_t size);
+
+snd_pcm_sframes_t snd_pcm_plugin_writen
+      (snd_pcm_t *pcm,
+       void **bufs,
+       snd_pcm_uframes_t size);
+
+snd_pcm_sframes_t snd_pcm_plugin_readi
+      (snd_pcm_t *pcm,
+       void *buffer,
+       snd_pcm_uframes_t size);
+
+snd_pcm_sframes_t snd_pcm_plugin_readn
+      (snd_pcm_t *pcm,
+       void **bufs,
+       snd_pcm_uframes_t size);
+
+snd_pcm_sframes_t snd_pcm_plugin_mmap_commit
+      (snd_pcm_t *pcm,
+       snd_pcm_uframes_t offset,
+       snd_pcm_uframes_t size);
+
+snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm);
+int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status);
+
 /* make local functions really local */
 #define snd_pcm_linear_get_index	snd1_pcm_linear_get_index
 #define snd_pcm_linear_put_index	snd1_pcm_linear_put_index
-- 
1.9.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] Fix forward/rewind support in iec958 plugin
  2014-04-23 18:40 [PATCH] Fix forward/rewind support in iec958 plugin Alexander E. Patrakov
@ 2014-04-24 11:19 ` David Henningsson
  2014-04-24 14:40   ` [PATCH v2] " Alexander E. Patrakov
  0 siblings, 1 reply; 7+ messages in thread
From: David Henningsson @ 2014-04-24 11:19 UTC (permalink / raw)
  To: Alexander E. Patrakov, alsa-devel; +Cc: tiwai



On 2014-04-23 20:40, Alexander E. Patrakov wrote:
> When forwarding or rewinding, the frame counter was not updated. This
> could result in corrupted channel status words or misplaced Z-type
> preamble.
> ---
> I found the issue by inspecting the code. However, I have no hardware
> to test this fix on.
>
>   src/pcm/pcm_iec958.c | 64 +++++++++++++++++++++++++++++++++++++++++++++-
>   src/pcm/pcm_plugin.c | 28 ++++++++++----------
>   src/pcm/pcm_plugin.h | 72 +++++++++++++++++++++++++++++++++++++++++++++++++---
>   3 files changed, 145 insertions(+), 19 deletions(-)
>
> diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c
> index d81b0a1..facf683 100644
> --- a/src/pcm/pcm_iec958.c
> +++ b/src/pcm/pcm_iec958.c
> @@ -416,6 +416,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,
> @@ -434,6 +463,39 @@ static const snd_pcm_ops_t snd_pcm_iec958_ops = {
>   	.set_chmap = snd_pcm_generic_set_chmap,
>   };
>
> +
> +static const snd_pcm_fast_ops_t snd_pcm_iec958_fast_ops = {
> +	.status = snd_pcm_plugin_status,
> +	.state = snd_pcm_generic_state,
> +	.hwsync = snd_pcm_generic_hwsync,
> +	.delay = snd_pcm_plugin_delay,
> +	.prepare = snd_pcm_plugin_prepare,
> +	.reset = snd_pcm_plugin_reset,
> +	.start = snd_pcm_generic_start,
> +	.drop = snd_pcm_generic_drop,
> +	.drain = snd_pcm_generic_drain,
> +	.pause = snd_pcm_generic_pause,
> +	.rewindable = snd_pcm_plugin_rewindable,
> +	.rewind = snd_pcm_iec958_rewind,
> +	.forwardable = snd_pcm_plugin_forwardable,
> +	.forward = snd_pcm_iec958_forward,
> +	.resume = snd_pcm_generic_resume,
> +	.link = snd_pcm_generic_link,
> +	.link_slaves = snd_pcm_generic_link_slaves,
> +	.unlink = snd_pcm_generic_unlink,
> +	.writei = snd_pcm_plugin_writei,
> +	.writen = snd_pcm_plugin_writen,
> +	.readi = snd_pcm_plugin_readi,
> +	.readn = snd_pcm_plugin_readn,
> +	.avail_update = snd_pcm_plugin_avail_update,
> +	.mmap_commit = snd_pcm_plugin_mmap_commit,
> +	.htimestamp = snd_pcm_generic_htimestamp,
> +	.poll_descriptors_count = snd_pcm_generic_poll_descriptors_count,
> +	.poll_descriptors = snd_pcm_generic_poll_descriptors,
> +	.poll_revents = snd_pcm_generic_poll_revents,
> +	.may_wait_for_avail_min = snd_pcm_generic_may_wait_for_avail_min,
> +};
> +
>   /**
>    * \brief Creates a new IEC958 subframe conversion PCM
>    * \param pcmp Returns created PCM handle
> @@ -495,7 +557,7 @@ 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;
> +	pcm->fast_ops = &snd_pcm_iec958_fast_ops;

Instead of making all pcm_plugin functions public, you can consider 
something like this:

ptr = malloc(sizeof(snd_pcm_fast_ops_t));
*ptr = snd_pcm_plugin_fast_ops;
ptr->rewind = snd_pcm_iec958_rewind;
ptr->forward = snd_pcm_iec958_forward;

pcm->fast_ops = ptr;

(and deallocate ptr somewhere else)

>   	pcm->private_data = iec;
>   	pcm->poll_fd = slave->poll_fd;
>   	pcm->poll_events = slave->poll_events;
> diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
> index 17157e8..022d908 100644
> --- a/src/pcm/pcm_plugin.c
> +++ b/src/pcm/pcm_plugin.c
> @@ -137,7 +137,7 @@ void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin)
>   	snd_atomic_write_init(&plugin->watom);
>   }
>
> -static int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
> +int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
>   {
>   	snd_pcm_plugin_t *plugin = pcm->private_data;
>   	snd_pcm_sframes_t sd;
> @@ -154,7 +154,7 @@ static int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
>   	return 0;
>   }
>
> -static int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
> +int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
>   {
>   	snd_pcm_plugin_t *plugin = pcm->private_data;
>   	int err;
> @@ -175,7 +175,7 @@ static int snd_pcm_plugin_prepare(snd_pcm_t *pcm)
>   	return 0;
>   }
>
> -static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
> +int snd_pcm_plugin_reset(snd_pcm_t *pcm)
>   {
>   	snd_pcm_plugin_t *plugin = pcm->private_data;
>   	int err;
> @@ -196,12 +196,12 @@ static int snd_pcm_plugin_reset(snd_pcm_t *pcm)
>   	return 0;
>   }
>
> -static snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm)
> +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);
> @@ -224,12 +224,12 @@ static snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t
>   	return (snd_pcm_sframes_t) sframes;
>   }
>
> -static snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm)
> +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);
> @@ -347,7 +347,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_read_areas(snd_pcm_t *pcm,
>   }
>
>
> -static snd_pcm_sframes_t
> +snd_pcm_sframes_t
>   snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
>   {
>   	snd_pcm_channel_area_t areas[pcm->channels];
> @@ -356,7 +356,7 @@ snd_pcm_plugin_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size
>   				   snd_pcm_plugin_write_areas);
>   }
>
> -static snd_pcm_sframes_t
> +snd_pcm_sframes_t
>   snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
>   {
>   	snd_pcm_channel_area_t areas[pcm->channels];
> @@ -365,7 +365,7 @@ snd_pcm_plugin_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
>   				   snd_pcm_plugin_write_areas);
>   }
>
> -static snd_pcm_sframes_t
> +snd_pcm_sframes_t
>   snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
>   {
>   	snd_pcm_channel_area_t areas[pcm->channels];
> @@ -374,7 +374,7 @@ snd_pcm_plugin_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
>   				  snd_pcm_plugin_read_areas);
>   }
>
> -static snd_pcm_sframes_t
> +snd_pcm_sframes_t
>   snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
>   {
>   	snd_pcm_channel_area_t areas[pcm->channels];
> @@ -383,7 +383,7 @@ snd_pcm_plugin_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
>   				  snd_pcm_plugin_read_areas);
>   }
>
> -static snd_pcm_sframes_t
> +snd_pcm_sframes_t
>   snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
>   			   snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
>   			   snd_pcm_uframes_t size)
> @@ -452,7 +452,7 @@ snd_pcm_plugin_mmap_commit(snd_pcm_t *pcm,
>   	return xfer;
>   }
>
> -static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
> +snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
>   {
>   	snd_pcm_plugin_t *plugin = pcm->private_data;
>   	snd_pcm_t *slave = plugin->gen.slave;
> @@ -516,7 +516,7 @@ static snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm)
>   	}
>   }
>
> -static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
> +int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
>   {
>   	snd_pcm_plugin_t *plugin = pcm->private_data;
>   	snd_pcm_sframes_t err;
> diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h
> index 7ee7c7f..7734369 100644
> --- a/src/pcm/pcm_plugin.h
> +++ b/src/pcm/pcm_plugin.h
> @@ -50,14 +50,42 @@ typedef struct {
>   } snd_pcm_plugin_t;	
>
>   /* make local functions really local */
> -#define snd_pcm_plugin_init \
> -	snd1_pcm_plugin_init
> -#define snd_pcm_plugin_fast_ops \
> -	snd1_pcm_plugin_fast_ops
>   #define snd_pcm_plugin_undo_read_generic \
>   	snd1_pcm_plugin_undo_read_generic
>   #define snd_pcm_plugin_undo_write_generic \
>   	snd1_pcm_plugin_undo_write_generic
> +#define snd_pcm_plugin_init \
> +	snd1_pcm_plugin_init
> +#define snd_pcm_plugin_delay \
> +	snd1_pcm_plugin_delay
> +#define snd_pcm_plugin_prepare \
> +	snd1_pcm_plugin_prepare
> +#define snd_pcm_plugin_reset \
> +	snd1_pcm_plugin_reset
> +#define snd_pcm_plugin_rewindable \
> +	snd1_pcm_plugin_rewindable
> +#define snd_pcm_plugin_rewind \
> +	snd1_pcm_plugin_rewind
> +#define snd_pcm_plugin_forwardable \
> +	snd1_pcm_plugin_forwardable
> +#define snd_pcm_plugin_forward \
> +	snd1_pcm_plugin_forward
> +#define snd_pcm_plugin_writei \
> +	snd1_pcm_plugin_writei
> +#define snd_pcm_plugin_writen \
> +	snd1_pcm_plugin_writen
> +#define snd_pcm_plugin_readi \
> +	snd1_pcm_plugin_readi
> +#define snd_pcm_plugin_readn \
> +	snd1_pcm_plugin_readn
> +#define snd_pcm_plugin_mmap_commit \
> +	snd1_pcm_plugin_mmap_commit
> +#define snd_pcm_plugin_avail_update \
> +	snd1_pcm_plugin_avail_update
> +#define snd_pcm_plugin_status \
> +	snd1_pcm_plugin_status
> +#define snd_pcm_plugin_fast_ops \
> +	snd1_pcm_plugin_fast_ops
>
>   void snd_pcm_plugin_init(snd_pcm_plugin_t *plugin);
>
> @@ -77,6 +105,42 @@ snd_pcm_sframes_t snd_pcm_plugin_undo_write_generic
>         snd_pcm_uframes_t res_size,		/* size of result areas */
>         snd_pcm_uframes_t slave_undo_size);
>
> +int snd_pcm_plugin_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
> +int snd_pcm_plugin_prepare(snd_pcm_t *pcm);
> +int snd_pcm_plugin_reset(snd_pcm_t *pcm);
> +snd_pcm_sframes_t snd_pcm_plugin_rewindable(snd_pcm_t *pcm);
> +snd_pcm_sframes_t snd_pcm_plugin_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
> +snd_pcm_sframes_t snd_pcm_plugin_forwardable(snd_pcm_t *pcm);
> +snd_pcm_sframes_t snd_pcm_plugin_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
> +
> +snd_pcm_sframes_t snd_pcm_plugin_writei
> +      (snd_pcm_t *pcm,
> +       const void *buffer,
> +       snd_pcm_uframes_t size);
> +
> +snd_pcm_sframes_t snd_pcm_plugin_writen
> +      (snd_pcm_t *pcm,
> +       void **bufs,
> +       snd_pcm_uframes_t size);
> +
> +snd_pcm_sframes_t snd_pcm_plugin_readi
> +      (snd_pcm_t *pcm,
> +       void *buffer,
> +       snd_pcm_uframes_t size);
> +
> +snd_pcm_sframes_t snd_pcm_plugin_readn
> +      (snd_pcm_t *pcm,
> +       void **bufs,
> +       snd_pcm_uframes_t size);
> +
> +snd_pcm_sframes_t snd_pcm_plugin_mmap_commit
> +      (snd_pcm_t *pcm,
> +       snd_pcm_uframes_t offset,
> +       snd_pcm_uframes_t size);
> +
> +snd_pcm_sframes_t snd_pcm_plugin_avail_update(snd_pcm_t *pcm);
> +int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status);
> +
>   /* make local functions really local */
>   #define snd_pcm_linear_get_index	snd1_pcm_linear_get_index
>   #define snd_pcm_linear_put_index	snd1_pcm_linear_put_index
>

-- 
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2] Fix forward/rewind support in iec958 plugin
  2014-04-24 11:19 ` David Henningsson
@ 2014-04-24 14:40   ` Alexander E. Patrakov
  2014-04-24 23:02     ` Raymond Yau
  2014-04-28 16:10     ` Takashi Iwai
  0 siblings, 2 replies; 7+ messages in thread
From: Alexander E. Patrakov @ 2014-04-24 14:40 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, Alexander E. Patrakov

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>
---
v2: As suggested by David Henningsson, patch a copy of
snd_pcm_plugin_fast_ops at runtime instead of making all plugin finctions
non-static. But, contrary to his proposal, I made fast_ops just a part of
struct snd_pcm_iec958, because the needed lifetime is exactly the same.

I still have no hardware to test this, and I strongly suspect that the
patch is wrong, because nobody else uses dynamic allocation of fast_ops.
A potentially suspicious operation would be to place a plug on top of this,
because plug copies fast_ops around. However, each time it closes a slave,
it also resets fast_ops to something sane, or at least I think so.

 src/pcm/pcm_iec958.c | 37 ++++++++++++++++++++++++++++++++++++-
 src/pcm/pcm_plugin.c |  4 ++--
 src/pcm/pcm_plugin.h |  6 ++++++
 3 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c
index d81b0a1..0c61fc1 100644
--- a/src/pcm/pcm_iec958.c
+++ b/src/pcm/pcm_iec958.c
@@ -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;
diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
index 17157e8..4ddf10c 100644
--- a/src/pcm/pcm_plugin.c
+++ b/src/pcm/pcm_plugin.c
@@ -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);
diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h
index 7ee7c7f..19e82c3 100644
--- a/src/pcm/pcm_plugin.h
+++ b/src/pcm/pcm_plugin.h
@@ -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;
 
-- 
1.9.2

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] Fix forward/rewind support in iec958 plugin
  2014-04-24 14:40   ` [PATCH v2] " Alexander E. Patrakov
@ 2014-04-24 23:02     ` Raymond Yau
  2014-04-25  6:00       ` Alexander E. Patrakov
  2014-04-25  8:09       ` Clemens Ladisch
  2014-04-28 16:10     ` Takashi Iwai
  1 sibling, 2 replies; 7+ messages in thread
From: Raymond Yau @ 2014-04-24 23:02 UTC (permalink / raw)
  To: Alexander E. Patrakov; +Cc: tiwai, alsa-devel

>
> When forwarding or rewinding, the frame counter was not updated. This
> could result in corrupted channel status words or misplaced Z-type
> preamble.

Do you mean it is the responsibility for a52 and dca plugin to return the
SAFE value returned by snd_pcm_rewindable and snd_pcm_forwardable since
they enocde the audio and padding zeros and write to IEC958 ?

>
> +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;
> +}
> +

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] Fix forward/rewind support in iec958 plugin
  2014-04-24 23:02     ` Raymond Yau
@ 2014-04-25  6:00       ` Alexander E. Patrakov
  2014-04-25  8:09       ` Clemens Ladisch
  1 sibling, 0 replies; 7+ messages in thread
From: Alexander E. Patrakov @ 2014-04-25  6:00 UTC (permalink / raw)
  To: alsa-devel; +Cc: Raymond Yau, david.henningsson

25.04.2014 05:02, Raymond Yau wrote:
>
>
> >
> > When forwarding or rewinding, the frame counter was not updated. This
> > could result in corrupted channel status words or misplaced Z-type
> > preamble.
>
> Do you mean it is the responsibility for a52 and dca plugin to return 
> the SAFE value returned by snd_pcm_rewindable and snd_pcm_forwardable 
> since they enocde the audio and padding zeros and write to IEC958 ?
>

Sorry, I don't understand the question, please reask differently if I am 
answering something else than what you mean here.

Neither a52 nor dca plugins use seeking under normal operation (when 
they themselves are not being seeked), they just write zeros when needed 
due to the IEC 61937-5 wrapping. Their implementations are in fact not 
seekable (they only pretend), and I will e-mail patches that enforce this.

What I mean in the patch is the following scenario involving an 
application that writes stereo data directly to the iec958 plugin.

1. Write 1920 samples.
2. Rewind 1919 samples.
3. Write 1919 samples.

Let's suppose that the counter was 0 initially, and the application 
pointer points at sample 0. Then, while encoding this to iec958 
subframes, the plugin would start the preamble sequence with Z. Result: 
ZYXYXYXYXY... in the output buffer after step 1. Z repeats every 192 
frames, as required by the standard. And the first subframe (with Z) now 
contains the first bit of the first status word. After writing 1920 
samples, the counter is still at 0, because it counts modulo 192.

After step 2, the application pointer points at sample 1, but the 
counter is 0 in the unpatched version and 1 in the patched one.

After step 3, the unpatched version writes the Z preamble and the first 
bit of the first status word. Result: ZYZYXYXYXY... The patched version 
writes the second bit of the first status word, i.e. just what should be 
in the buffer. Also, it puts the X preamble. Result: ZYXYXYXYXY..., just 
what there should be.

So, after the patch, the iec958 plugin properly supports arbitrary 
seeking, just like a normal hardware device, and should be just as 
usable by hypothetical seekable versions of the a52 and dca plugins.

-- 
Alexander E. Patrakov

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] Fix forward/rewind support in iec958 plugin
  2014-04-24 23:02     ` Raymond Yau
  2014-04-25  6:00       ` Alexander E. Patrakov
@ 2014-04-25  8:09       ` Clemens Ladisch
  1 sibling, 0 replies; 7+ messages in thread
From: Clemens Ladisch @ 2014-04-25  8:09 UTC (permalink / raw)
  To: Raymond Yau, Alexander E. Patrakov; +Cc: tiwai, alsa-devel

Raymond Yau wrote:
>> When forwarding or rewinding, the frame counter was not updated. This
>> could result in corrupted channel status words or misplaced Z-type
>> preamble.
>
> Do you mean it is the responsibility for a52 and dca plugin to return the
> SAFE value returned by snd_pcm_rewindable and snd_pcm_forwardable since
> they enocde the audio and padding zeros and write to IEC958 ?

The a52/dca plugins create data to be transferred over S/PDIF, but this
does not imply they use the iec958 plugin.

The iec958 plugin is used for sound cards that do not have a hardware
IEC958 encoder.  This is very unlikely nowadays.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] Fix forward/rewind support in iec958 plugin
  2014-04-24 14:40   ` [PATCH v2] " Alexander E. Patrakov
  2014-04-24 23:02     ` Raymond Yau
@ 2014-04-28 16:10     ` Takashi Iwai
  1 sibling, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2014-04-28 16:10 UTC (permalink / raw)
  To: Alexander E. Patrakov; +Cc: alsa-devel

At Thu, 24 Apr 2014 20:40:06 +0600,
Alexander E. Patrakov wrote:
> 
> 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>
> ---
> v2: As suggested by David Henningsson, patch a copy of
> snd_pcm_plugin_fast_ops at runtime instead of making all plugin finctions
> non-static. But, contrary to his proposal, I made fast_ops just a part of
> struct snd_pcm_iec958, because the needed lifetime is exactly the same.
> 
> I still have no hardware to test this, and I strongly suspect that the
> patch is wrong, because nobody else uses dynamic allocation of fast_ops.
> A potentially suspicious operation would be to place a plug on top of this,
> because plug copies fast_ops around. However, each time it closes a slave,
> it also resets fast_ops to something sane, or at least I think so.

The embedded fast_ops should work fine, so I applied the patch as is
now.  Let's see whether it really fixes the issues properly...


thanks,

Takashi

> 
>  src/pcm/pcm_iec958.c | 37 ++++++++++++++++++++++++++++++++++++-
>  src/pcm/pcm_plugin.c |  4 ++--
>  src/pcm/pcm_plugin.h |  6 ++++++
>  3 files changed, 44 insertions(+), 3 deletions(-)
> 
> diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c
> index d81b0a1..0c61fc1 100644
> --- a/src/pcm/pcm_iec958.c
> +++ b/src/pcm/pcm_iec958.c
> @@ -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;
> diff --git a/src/pcm/pcm_plugin.c b/src/pcm/pcm_plugin.c
> index 17157e8..4ddf10c 100644
> --- a/src/pcm/pcm_plugin.c
> +++ b/src/pcm/pcm_plugin.c
> @@ -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);
> diff --git a/src/pcm/pcm_plugin.h b/src/pcm/pcm_plugin.h
> index 7ee7c7f..19e82c3 100644
> --- a/src/pcm/pcm_plugin.h
> +++ b/src/pcm/pcm_plugin.h
> @@ -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;
>  
> -- 
> 1.9.2
> 
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-04-28 16:10 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-23 18:40 [PATCH] Fix forward/rewind support in iec958 plugin Alexander E. Patrakov
2014-04-24 11:19 ` David Henningsson
2014-04-24 14:40   ` [PATCH v2] " Alexander E. Patrakov
2014-04-24 23:02     ` Raymond Yau
2014-04-25  6:00       ` Alexander E. Patrakov
2014-04-25  8:09       ` Clemens Ladisch
2014-04-28 16:10     ` Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox