diff mbox series

[1/2] alsa: pcm: add unsupported OPS

Message ID 1562583889-2109-2-git-send-email-amiartus@de.adit-jv.com (mailing list archive)
State New, archived
Headers show
Series expand dshare to allow audio clock when not streaming data | expand

Commit Message

Adam Miartus July 8, 2019, 11:04 a.m. UTC
From: Andreas Pape <apape@de.adit-jv.com>

Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
---
 src/pcm/Makefile.am       |   4 +-
 src/pcm/pcm_unsupported.c | 265 ++++++++++++++++++++++++++++++++++++++++++++++
 src/pcm/pcm_unsupported.h | 166 +++++++++++++++++++++++++++++
 3 files changed, 433 insertions(+), 2 deletions(-)
 create mode 100644 src/pcm/pcm_unsupported.c
 create mode 100644 src/pcm/pcm_unsupported.h

Comments

Takashi Iwai July 9, 2019, 12:25 p.m. UTC | #1
On Mon, 08 Jul 2019 13:04:48 +0200,
Adam Miartus wrote:
> 
> From: Andreas Pape <apape@de.adit-jv.com>
> 
> Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
> Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>

No description isn't good at all.  There must be something you can
explain in details here.

About the changes:

> +#define PCM_UNSUPPORTED_ERR (-ENOSYS)
> +void snd_pcm_unsupported_dump(snd_pcm_t *pcm, snd_output_t *out)
> +{
> +	snd_output_printf(out, "unsupported\n");
> +}

IMO, we don't need to show anything if it's dummy.
And, maybe it's more straightforward to let the PCM core allow NULL
ops?


thanks,

Takashi
Adam Miartus July 10, 2019, 2:58 p.m. UTC | #2
> -----Original Message-----
> From: Takashi Iwai <tiwai@suse.de>
> Sent: Dienstag, 9. Juli 2019 14:25
> To: Miartus, Adam (Arion Recruitment; ADITG/ESM) <amiartus@de.adit-
> jv.com>
> Cc: alsa-devel@alsa-project.org; Pape, Andreas (ADITG/ESS1)
> <apape@de.adit-jv.com>
> Subject: Re: [ALSA patch] [PATCH 1/2] alsa: pcm: add unsupported OPS
> 
> On Mon, 08 Jul 2019 13:04:48 +0200,
> Adam Miartus wrote:
> >
> > From: Andreas Pape <apape@de.adit-jv.com>
> >
> > Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
> > Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
> 
> No description isn't good at all.  There must be something you can
> explain in details here.

Certainly, I will add explanation in patch v2.

> 
> About the changes:
> 
> > +#define PCM_UNSUPPORTED_ERR (-ENOSYS)
> > +void snd_pcm_unsupported_dump(snd_pcm_t *pcm, snd_output_t
> *out)
> > +{
> > +	snd_output_printf(out, "unsupported\n");
> > +}
> 
> IMO, we don't need to show anything if it's dummy.
> And, maybe it's more straightforward to let the PCM core allow NULL
> ops?
> 

If you agree I could add following in patch v2, then we could drop snd_pcm_unsupported_dump function altogether

diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
index e0ceccc..4d91d4d 100644
--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2277,7 +2277,8 @@ int snd_pcm_dump(snd_pcm_t *pcm, snd_output_t *out)
 {
        assert(pcm);
        assert(out);
-       pcm->ops->dump(pcm->op_arg, out);
+       if (pcm->ops->dump)
+               pcm->ops->dump(pcm->op_arg, out);
        return 0;
 }

Please let me know if you agree with proposed changes and I will prepare patch v2.

Adam
Takashi Iwai July 10, 2019, 2:59 p.m. UTC | #3
On Wed, 10 Jul 2019 16:58:06 +0200,
Miartus, Adam (Arion Recruitment; ADITG/ESM) wrote:
> 
> > -----Original Message-----
> > From: Takashi Iwai <tiwai@suse.de>
> > Sent: Dienstag, 9. Juli 2019 14:25
> > To: Miartus, Adam (Arion Recruitment; ADITG/ESM) <amiartus@de.adit-
> > jv.com>
> > Cc: alsa-devel@alsa-project.org; Pape, Andreas (ADITG/ESS1)
> > <apape@de.adit-jv.com>
> > Subject: Re: [ALSA patch] [PATCH 1/2] alsa: pcm: add unsupported OPS
> > 
> > On Mon, 08 Jul 2019 13:04:48 +0200,
> > Adam Miartus wrote:
> > >
> > > From: Andreas Pape <apape@de.adit-jv.com>
> > >
> > > Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
> > > Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
> > 
> > No description isn't good at all.  There must be something you can
> > explain in details here.
> 
> Certainly, I will add explanation in patch v2.
> 
> > 
> > About the changes:
> > 
> > > +#define PCM_UNSUPPORTED_ERR (-ENOSYS)
> > > +void snd_pcm_unsupported_dump(snd_pcm_t *pcm, snd_output_t
> > *out)
> > > +{
> > > +	snd_output_printf(out, "unsupported\n");
> > > +}
> > 
> > IMO, we don't need to show anything if it's dummy.
> > And, maybe it's more straightforward to let the PCM core allow NULL
> > ops?
> > 
> 
> If you agree I could add following in patch v2, then we could drop snd_pcm_unsupported_dump function altogether
> 
> diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
> index e0ceccc..4d91d4d 100644
> --- a/src/pcm/pcm.c
> +++ b/src/pcm/pcm.c
> @@ -2277,7 +2277,8 @@ int snd_pcm_dump(snd_pcm_t *pcm, snd_output_t *out)
>  {
>         assert(pcm);
>         assert(out);
> -       pcm->ops->dump(pcm->op_arg, out);
> +       if (pcm->ops->dump)
> +               pcm->ops->dump(pcm->op_arg, out);
>         return 0;
>  }

I *guess* this would be simpler in the end, although I'm fine with
your original idea, too.  Let's see and compare the both results.


thanks,

Takashi
Adam Miartus July 11, 2019, 2:58 p.m. UTC | #4
> -----Original Message-----
> From: Takashi Iwai <tiwai@suse.de>
> Sent: Mittwoch, 10. Juli 2019 17:00
> To: Miartus, Adam (Arion Recruitment; ADITG/ESM) <amiartus@de.adit-
> jv.com>
> Cc: alsa-devel@alsa-project.org; Pape, Andreas (ADITG/ESS1)
> <apape@de.adit-jv.com>
> Subject: Re: [ALSA patch] [PATCH 1/2] alsa: pcm: add unsupported OPS
> 
> On Wed, 10 Jul 2019 16:58:06 +0200,
> Miartus, Adam (Arion Recruitment; ADITG/ESM) wrote:
> >
> > > -----Original Message-----
> > > From: Takashi Iwai <tiwai@suse.de>
> > > Sent: Dienstag, 9. Juli 2019 14:25
> > > To: Miartus, Adam (Arion Recruitment; ADITG/ESM) <amiartus@de.adit-
> > > jv.com>
> > > Cc: alsa-devel@alsa-project.org; Pape, Andreas (ADITG/ESS1)
> > > <apape@de.adit-jv.com>
> > > Subject: Re: [ALSA patch] [PATCH 1/2] alsa: pcm: add unsupported OPS
> > >
> > > On Mon, 08 Jul 2019 13:04:48 +0200,
> > > Adam Miartus wrote:
> > > >
> > > > From: Andreas Pape <apape@de.adit-jv.com>
> > > >
> > > > Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
> > > > Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
> > >
> > > No description isn't good at all.  There must be something you can
> > > explain in details here.
> >
> > Certainly, I will add explanation in patch v2.
> >
> > >
> > > About the changes:
> > >
> > > > +#define PCM_UNSUPPORTED_ERR (-ENOSYS)
> > > > +void snd_pcm_unsupported_dump(snd_pcm_t *pcm, snd_output_t
> > > *out)
> > > > +{
> > > > +	snd_output_printf(out, "unsupported\n");
> > > > +}
> > >
> > > IMO, we don't need to show anything if it's dummy.
> > > And, maybe it's more straightforward to let the PCM core allow NULL
> > > ops?
> > >
> >
> > If you agree I could add following in patch v2, then we could drop
> snd_pcm_unsupported_dump function altogether
> >
> > diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
> > index e0ceccc..4d91d4d 100644
> > --- a/src/pcm/pcm.c
> > +++ b/src/pcm/pcm.c
> > @@ -2277,7 +2277,8 @@ int snd_pcm_dump(snd_pcm_t *pcm,
> snd_output_t *out)
> >  {
> >         assert(pcm);
> >         assert(out);
> > -       pcm->ops->dump(pcm->op_arg, out);
> > +       if (pcm->ops->dump)
> > +               pcm->ops->dump(pcm->op_arg, out);
> >         return 0;
> >  }
> 
> I *guess* this would be simpler in the end, although I'm fine with
> your original idea, too.  Let's see and compare the both results.

Yes I agree, it would even be better to remove the pcm_unsupported.c altogether.
I had a look at how snd_pcm_ops_t and snd_pcm_fast_ops_t callbacks are used in alsa-lib
and in most cases (90% or more) it is assumed that the function pointer is valid without
checking for NULL.

Unfortunately, not all functions in ops and fast_ops share the same return type,
so checking for null pointer in a macro is not straightforward. One way I see is to add:

if (ops->callback == NULL)
	return -ENOSYS;

check in every occurrence of ops callback call in source code, then we could drop
pcm_unsupported.c file completely.

Optionally we could add a set of macros such as (it compiled both in gcc and in clang)

#define snd_callback_int(fpointer, ...) ({ \
	int result; \
	if (fpointer == NULL) \
		result = -ENOSYS; \
	else \
		result = fpointer(__VA_ARGS__); \
	result; \
})

For each ops function return types, currently these are:
int, void, snd_pcm_chmap_query_t**, snd_pcm_chmap_t *, 
snd_pcm_state_t, snd_pcm_sframes_t

So, the variants for macros would be:
snd_callback_void
snd_callback_int
snd_callback_ptr
snd_callback_sframes

This might seem like cumbersome approach but it would save lines of code
and provide a way to check for null callback pointer, which is currently not
done in most cases.

What do you think about these two approaches, what could you consider
correct and able to be merged?

Adam
Takashi Iwai July 16, 2019, 5:53 a.m. UTC | #5
On Thu, 11 Jul 2019 16:58:34 +0200,
Miartus, Adam (Arion Recruitment; ADITG/ESM) wrote:
> 
> > -----Original Message-----
> > From: Takashi Iwai <tiwai@suse.de>
> > Sent: Mittwoch, 10. Juli 2019 17:00
> > To: Miartus, Adam (Arion Recruitment; ADITG/ESM) <amiartus@de.adit-
> > jv.com>
> > Cc: alsa-devel@alsa-project.org; Pape, Andreas (ADITG/ESS1)
> > <apape@de.adit-jv.com>
> > Subject: Re: [ALSA patch] [PATCH 1/2] alsa: pcm: add unsupported OPS
> > 
> > On Wed, 10 Jul 2019 16:58:06 +0200,
> > Miartus, Adam (Arion Recruitment; ADITG/ESM) wrote:
> > >
> > > > -----Original Message-----
> > > > From: Takashi Iwai <tiwai@suse.de>
> > > > Sent: Dienstag, 9. Juli 2019 14:25
> > > > To: Miartus, Adam (Arion Recruitment; ADITG/ESM) <amiartus@de.adit-
> > > > jv.com>
> > > > Cc: alsa-devel@alsa-project.org; Pape, Andreas (ADITG/ESS1)
> > > > <apape@de.adit-jv.com>
> > > > Subject: Re: [ALSA patch] [PATCH 1/2] alsa: pcm: add unsupported OPS
> > > >
> > > > On Mon, 08 Jul 2019 13:04:48 +0200,
> > > > Adam Miartus wrote:
> > > > >
> > > > > From: Andreas Pape <apape@de.adit-jv.com>
> > > > >
> > > > > Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
> > > > > Signed-off-by: Adam Miartus <amiartus@de.adit-jv.com>
> > > >
> > > > No description isn't good at all.  There must be something you can
> > > > explain in details here.
> > >
> > > Certainly, I will add explanation in patch v2.
> > >
> > > >
> > > > About the changes:
> > > >
> > > > > +#define PCM_UNSUPPORTED_ERR (-ENOSYS)
> > > > > +void snd_pcm_unsupported_dump(snd_pcm_t *pcm, snd_output_t
> > > > *out)
> > > > > +{
> > > > > +	snd_output_printf(out, "unsupported\n");
> > > > > +}
> > > >
> > > > IMO, we don't need to show anything if it's dummy.
> > > > And, maybe it's more straightforward to let the PCM core allow NULL
> > > > ops?
> > > >
> > >
> > > If you agree I could add following in patch v2, then we could drop
> > snd_pcm_unsupported_dump function altogether
> > >
> > > diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c
> > > index e0ceccc..4d91d4d 100644
> > > --- a/src/pcm/pcm.c
> > > +++ b/src/pcm/pcm.c
> > > @@ -2277,7 +2277,8 @@ int snd_pcm_dump(snd_pcm_t *pcm,
> > snd_output_t *out)
> > >  {
> > >         assert(pcm);
> > >         assert(out);
> > > -       pcm->ops->dump(pcm->op_arg, out);
> > > +       if (pcm->ops->dump)
> > > +               pcm->ops->dump(pcm->op_arg, out);
> > >         return 0;
> > >  }
> > 
> > I *guess* this would be simpler in the end, although I'm fine with
> > your original idea, too.  Let's see and compare the both results.
> 
> Yes I agree, it would even be better to remove the pcm_unsupported.c altogether.
> I had a look at how snd_pcm_ops_t and snd_pcm_fast_ops_t callbacks are used in alsa-lib
> and in most cases (90% or more) it is assumed that the function pointer is valid without
> checking for NULL.
> 
> Unfortunately, not all functions in ops and fast_ops share the same return type,
> so checking for null pointer in a macro is not straightforward. One way I see is to add:
> 
> if (ops->callback == NULL)
> 	return -ENOSYS;
> 
> check in every occurrence of ops callback call in source code, then we could drop
> pcm_unsupported.c file completely.
> 
> Optionally we could add a set of macros such as (it compiled both in gcc and in clang)
> 
> #define snd_callback_int(fpointer, ...) ({ \
> 	int result; \
> 	if (fpointer == NULL) \
> 		result = -ENOSYS; \
> 	else \
> 		result = fpointer(__VA_ARGS__); \
> 	result; \
> })

I don't think we need to put too tricky code there.
Even if it's a bit longer, the simple open code should be more
understandable.  So just add simply the NULL check at each place
instead of macro including the control flow inside.


thanks,

Takashi
diff mbox series

Patch

diff --git a/src/pcm/Makefile.am b/src/pcm/Makefile.am
index 8edbd0b..ba07869 100644
--- a/src/pcm/Makefile.am
+++ b/src/pcm/Makefile.am
@@ -8,7 +8,7 @@  libpcm_la_SOURCES = mask.c interval.c \
 		    pcm_hw.c pcm_misc.c pcm_mmap.c pcm_symbols.c
 
 if BUILD_PCM_PLUGIN
-libpcm_la_SOURCES += pcm_generic.c pcm_plugin.c
+libpcm_la_SOURCES += pcm_generic.c pcm_plugin.c pcm_unsupported.c
 endif
 if BUILD_PCM_PLUGIN_COPY
 libpcm_la_SOURCES += pcm_copy.c
@@ -108,7 +108,7 @@  EXTRA_DIST = pcm_dmix_i386.c pcm_dmix_x86_64.c pcm_dmix_generic.c
 noinst_HEADERS = pcm_local.h pcm_plugin.h mask.h mask_inline.h \
 	         interval.h interval_inline.h plugin_ops.h ladspa.h \
 		 pcm_direct.h pcm_dmix_i386.h pcm_dmix_x86_64.h \
-		 pcm_generic.h pcm_ext_parm.h
+		 pcm_generic.h pcm_ext_parm.h pcm_unsupported.h
 
 alsadir = $(datadir)/alsa
 
diff --git a/src/pcm/pcm_unsupported.c b/src/pcm/pcm_unsupported.c
new file mode 100644
index 0000000..b7abf04
--- /dev/null
+++ b/src/pcm/pcm_unsupported.c
@@ -0,0 +1,265 @@ 
+/**
+ * \file pcm/pcm_unsupported.c
+ * \ingroup PCM
+ * \brief PCM Unsupported Interface
+ * \author Andreas Pape <apape@de.adit-jv.com>
+ * \date 2019
+ */
+/*
+ *  PCM - Common plugin code for unsupported operations
+ *  Copyright (c) 2019 by Andreas Pape <apape@de.adit-jv.com>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "pcm_local.h"
+#include "pcm_unsupported.h"
+
+#ifndef DOC_HIDDEN
+
+#define PCM_UNSUPPORTED_ERR (-ENOSYS)
+void snd_pcm_unsupported_dump(snd_pcm_t *pcm, snd_output_t *out)
+{
+	snd_output_printf(out, "unsupported\n");
+}
+
+int snd_pcm_unsupported_close(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_nonblock(snd_pcm_t *pcm, int nonblock)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_async(snd_pcm_t *pcm, int sig, pid_t pid)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_poll_descriptors_count(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_hw_free(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_prepare(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_state_t snd_pcm_unsupported_state(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_hwsync(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_reset(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_start(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_drop(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_drain(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_pause(snd_pcm_t *pcm, int enable)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_resume(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_forwardable(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_rewindable(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_unlink(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_mmap_commit(snd_pcm_t *pcm,
+					      snd_pcm_uframes_t offset,
+					      snd_pcm_uframes_t size)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_sframes_t snd_pcm_unsupported_avail_update(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
+			       snd_htimestamp_t *tstamp)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_real_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
+				    snd_htimestamp_t *tstamp)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_mmap(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_munmap(snd_pcm_t *pcm)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+snd_pcm_chmap_query_t **snd_pcm_unsupported_query_chmaps(snd_pcm_t *pcm)
+{
+	return NULL;
+}
+
+snd_pcm_chmap_t *snd_pcm_unsupported_get_chmap(snd_pcm_t *pcm)
+{
+	return NULL;
+}
+
+int snd_pcm_unsupported_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+int snd_pcm_unsupported_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail ATTRIBUTE_UNUSED)
+{
+	return PCM_UNSUPPORTED_ERR;
+}
+
+
+#endif /* DOC_HIDDEN */
diff --git a/src/pcm/pcm_unsupported.h b/src/pcm/pcm_unsupported.h
new file mode 100644
index 0000000..13e4d1b
--- /dev/null
+++ b/src/pcm/pcm_unsupported.h
@@ -0,0 +1,166 @@ 
+/*
+ *  PCM - Common plugin code for unsupported operations
+ *  Copyright (c) 2017 by Andreas Pape <apape@de.adit-jv.com>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as
+ *   published by the Free Software Foundation; either version 2.1 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+  
+
+/* make local functions really local */
+#define snd_pcm_unsupported_dump \
+	snd1_pcm_unsupported_dump
+#define snd_pcm_unsupported_close \
+	snd1_pcm_unsupported_close
+#define snd_pcm_unsupported_nonblock \
+	snd1_pcm_unsupported_nonblock
+#define snd_pcm_unsupported_async \
+	snd1_pcm_unsupported_async
+#define snd_pcm_unsupported_poll_descriptors_count \
+	snd1_pcm_unsupported_poll_descriptors_count
+#define snd_pcm_unsupported_poll_descriptors \
+	snd1_pcm_unsupported_poll_descriptors
+#define snd_pcm_unsupported_poll_revents \
+	snd1_pcm_unsupported_poll_revents
+#define snd_pcm_unsupported_info \
+	snd1_pcm_unsupported_info
+#define snd_pcm_unsupported_hw_free \
+	snd1_pcm_unsupported_hw_free
+#define snd_pcm_unsupported_sw_params \
+	snd1_pcm_unsupported_sw_params
+#define snd_pcm_unsupported_hw_refine \
+	snd1_pcm_unsupported_hw_refine
+#define snd_pcm_unsupported_hw_params \
+	snd1_pcm_unsupported_hw_params
+#define snd_pcm_unsupported_channel_info \
+	snd1_pcm_unsupported_channel_info
+#define snd_pcm_unsupported_channel_info_no_buffer \
+	snd1_pcm_unsupported_channel_info_no_buffer
+#define snd_pcm_unsupported_status \
+	snd1_pcm_unsupported_status
+#define snd_pcm_unsupported_state \
+	snd1_pcm_unsupported_state
+#define snd_pcm_unsupported_prepare \
+	snd1_pcm_unsupported_prepare
+#define snd_pcm_unsupported_hwsync \
+	snd1_pcm_unsupported_hwsync
+#define snd_pcm_unsupported_reset \
+	snd1_pcm_unsupported_reset
+#define snd_pcm_unsupported_start \
+	snd1_pcm_unsupported_start
+#define snd_pcm_unsupported_drop \
+	snd1_pcm_unsupported_drop
+#define snd_pcm_unsupported_drain \
+	snd1_pcm_unsupported_drain
+#define snd_pcm_unsupported_pause \
+	snd1_pcm_unsupported_pause
+#define snd_pcm_unsupported_resume \
+	snd1_pcm_unsupported_resume
+#define snd_pcm_unsupported_delay \
+	snd1_pcm_unsupported_delay
+#define snd_pcm_unsupported_forwardable \
+	snd1_pcm_unsupported_forwardable
+#define snd_pcm_unsupported_forward \
+	snd1_pcm_unsupported_forward
+#define snd_pcm_unsupported_rewindable \
+	snd1_pcm_unsupported_rewindable
+#define snd_pcm_unsupported_rewind \
+	snd1_pcm_unsupported_rewind
+#define snd_pcm_unsupported_link \
+	snd1_pcm_unsupported_link
+#define snd_pcm_unsupported_link_slaves \
+	snd1_pcm_unsupported_link_slaves
+#define snd_pcm_unsupported_unlink \
+	snd1_pcm_unsupported_unlink
+#define snd_pcm_unsupported_writei \
+	snd1_pcm_unsupported_writei
+#define snd_pcm_unsupported_writen \
+	snd1_pcm_unsupported_writen
+#define snd_pcm_unsupported_readi \
+	snd1_pcm_unsupported_readi
+#define snd_pcm_unsupported_readn \
+	snd1_pcm_unsupported_readn
+#define snd_pcm_unsupported_mmap_commit \
+	snd1_pcm_unsupported_mmap_commit
+#define snd_pcm_unsupported_avail_update	\
+	snd1_pcm_unsupported_avail_update
+#define snd_pcm_unsupported_htimestamp	\
+	snd1_pcm_unsupported_htimestamp
+#define snd_pcm_unsupported_real_htimestamp	\
+	snd1_pcm_unsupported_real_htimestamp
+#define snd_pcm_unsupported_mmap \
+	snd1_pcm_unsupported_mmap
+#define snd_pcm_unsupported_munmap \
+	snd1_pcm_unsupported_munmap
+#define snd_pcm_unsupported_query_chmaps \
+	snd1_pcm_unsupported_query_chmaps
+#define snd_pcm_unsupported_get_chmap \
+	snd1_pcm_unsupported_get_chmap
+#define snd_pcm_unsupported_set_chmap \
+	snd1_pcm_unsupported_set_chmap
+#define snd_pcm_unsupported_may_wait_for_avail_min \
+	snd1_pcm_unsupported_may_wait_for_avail_min
+
+int snd_pcm_unsupported_close(snd_pcm_t *pcm);
+int snd_pcm_unsupported_nonblock(snd_pcm_t *pcm, int nonblock);
+int snd_pcm_unsupported_async(snd_pcm_t *pcm, int sig, pid_t pid);
+int snd_pcm_unsupported_poll_descriptors_count(snd_pcm_t *pcm);
+int snd_pcm_unsupported_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space);
+int snd_pcm_unsupported_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
+int snd_pcm_unsupported_info(snd_pcm_t *pcm, snd_pcm_info_t * info);
+int snd_pcm_unsupported_hw_free(snd_pcm_t *pcm);
+int snd_pcm_unsupported_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
+int snd_pcm_unsupported_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
+int snd_pcm_unsupported_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
+int snd_pcm_unsupported_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info);
+int snd_pcm_unsupported_channel_info_no_buffer(snd_pcm_t *pcm, snd_pcm_channel_info_t * info);
+int snd_pcm_unsupported_status(snd_pcm_t *pcm, snd_pcm_status_t * status);
+snd_pcm_state_t snd_pcm_unsupported_state(snd_pcm_t *pcm);
+int snd_pcm_unsupported_prepare(snd_pcm_t *pcm);
+int snd_pcm_unsupported_hwsync(snd_pcm_t *pcm);
+int snd_pcm_unsupported_reset(snd_pcm_t *pcm);
+int snd_pcm_unsupported_start(snd_pcm_t *pcm);
+int snd_pcm_unsupported_drop(snd_pcm_t *pcm);
+int snd_pcm_unsupported_drain(snd_pcm_t *pcm);
+int snd_pcm_unsupported_pause(snd_pcm_t *pcm, int enable);
+int snd_pcm_unsupported_resume(snd_pcm_t *pcm);
+int snd_pcm_unsupported_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp);
+snd_pcm_sframes_t snd_pcm_unsupported_forwardable(snd_pcm_t *pcm);
+snd_pcm_sframes_t snd_pcm_unsupported_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_unsupported_rewindable(snd_pcm_t *pcm);
+snd_pcm_sframes_t snd_pcm_unsupported_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames);
+int snd_pcm_unsupported_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2);
+int snd_pcm_unsupported_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master);
+int snd_pcm_unsupported_unlink(snd_pcm_t *pcm);
+snd_pcm_sframes_t snd_pcm_unsupported_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
+snd_pcm_sframes_t snd_pcm_unsupported_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
+snd_pcm_sframes_t snd_pcm_unsupported_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);
+snd_pcm_sframes_t snd_pcm_unsupported_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size);
+snd_pcm_sframes_t snd_pcm_unsupported_mmap_commit(snd_pcm_t *pcm,
+					      snd_pcm_uframes_t offset,
+					      snd_pcm_uframes_t size);
+snd_pcm_sframes_t snd_pcm_unsupported_avail_update(snd_pcm_t *pcm);
+int snd_pcm_unsupported_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
+			       snd_htimestamp_t *timestamp);
+int snd_pcm_unsupported_real_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
+				    snd_htimestamp_t *tstamp);
+int snd_pcm_unsupported_mmap(snd_pcm_t *pcm);
+int snd_pcm_unsupported_munmap(snd_pcm_t *pcm);
+snd_pcm_chmap_query_t **snd_pcm_unsupported_query_chmaps(snd_pcm_t *pcm);
+snd_pcm_chmap_t *snd_pcm_unsupported_get_chmap(snd_pcm_t *pcm);
+int snd_pcm_unsupported_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
+int snd_pcm_unsupported_may_wait_for_avail_min(snd_pcm_t *pcm, snd_pcm_uframes_t avail);
+