[alsa-devel] get rid of controls with snd_ctl_remove

Takashi Iwai tiwai at suse.de
Fri Aug 29 18:42:08 CEST 2008


At Fri, 29 Aug 2008 14:56:33 +0100,
Liam Girdwood wrote:
> 
> On Fri, 2008-08-29 at 15:41 +0200, Takashi Iwai wrote:
> > At Fri, 29 Aug 2008 14:16:52 +0100,
> > Liam Girdwood wrote:
> 
> > > I'd prefer an addition to our API to handle this more _common_ case
> > > rather than just removing controls. 
> > > 
> > > Something where we can mark controls as "disabled" so alsamixer and
> > > friends wont render/get them. This would also allow scenario code to
> > > disable relevant mixers and then re-enable when required.
> > 
> > Something like below?
> > 
> > 
> > Takashi
> > 
> > diff --git a/sound/core/control.c b/sound/core/control.c
> > index 3c5e746..c6f7062 100644
> > --- a/sound/core/control.c
> > +++ b/sound/core/control.c
> > @@ -410,6 +410,52 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
> >  EXPORT_SYMBOL(snd_ctl_remove_id);
> >  
> >  /**
> > + * snd_ctl_activate_id - activate/inactivate the control of the given id
> > + * @card: the card instance
> > + * @id: the control id to activate/inactivate
> > + * @active: non-zero to activate
> > + *
> > + * Finds the control instance with the given id, and activate or
> > + * inactivate the control together with notification, if changed.
> > + * 
> > + * Returns 0 if unchanged, 1 if changed, or a negative error code on failure.
> > + */
> > +int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
> > +			int active)
> > +{
> > +	struct snd_kcontrol *kctl;
> > +	struct snd_kcontrol_volatile *vd;
> > +	unsigned int index_offset;
> > +	int ret;
> > +
> > +	down_write(&card->controls_rwsem);
> > +	kctl = snd_ctl_find_id(card, id);
> > +	if (kctl == NULL) {
> > +		up_write(&card->controls_rwsem);
> > +		return -ENOENT;
> > +	}
> > +	index_offset = snd_ctl_get_ioff(kctl, &control->id);
> > +	vd = &kctl->vd[index_offset];
> > +	ret = 0;
> > +	if (active) {
> > +		if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE))
> > +			goto unlock;
> > +		vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
> > +	} else {
> > +		if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)
> > +			goto unlock;
> > +		vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
> > +	}
> > +	ret = 1;
> > + unlock:
> > +	up_write(&card->controls_rwsem);
> > +	if (ret)
> > +		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL(snd_ctl_activate_id);
> > +
> > +/**
> >   * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it
> >   * @file: active control handle
> >   * @id: the control id to remove
> 
> Wow - that was quick !
> 
> Yes, exactly :) We can now add this to our machine drivers to disable
> never used controls (for each machine) and also call this when scenario
> changes too.
> 
> Even more interestingly, it could also be called by DAPM......

Good to hear that.  Just let me know if you need this in the upstream.
I don't want to push such an API addition too early before any use.

FWIW, below is the latest version, found in my sound-unstable tree.


thanks,

Takashi


From c4ef566498f37140bcef852109e44bea580f4bc8 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai at suse.de>
Date: Fri, 29 Aug 2008 16:09:01 +0200
Subject: [PATCH] ALSA: Add snd_ctl_activate_id()

Added a new API function snd_ctl_activate_id() for activate / inactivate
the control element dynamically.

Signed-off-by: Takashi Iwai <tiwai at suse.de>

diff --git a/include/sound/control.h b/include/sound/control.h
index 4721b4b..6c0002a 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -114,6 +114,8 @@ int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
 int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
 int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
 int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
+int snd_ctl_activate_id(struct snd_card * card, struct snd_ctl_elem_id *id,
+			int active);
 struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
 struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
 
diff --git a/sound/core/control.c b/sound/core/control.c
index 3c5e746..c6f7062 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -410,6 +410,52 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
 EXPORT_SYMBOL(snd_ctl_remove_id);
 
 /**
+ * snd_ctl_activate_id - activate/inactivate the control of the given id
+ * @card: the card instance
+ * @id: the control id to activate/inactivate
+ * @active: non-zero to activate
+ *
+ * Finds the control instance with the given id, and activate or
+ * inactivate the control together with notification, if changed.
+ * 
+ * Returns 0 if unchanged, 1 if changed, or a negative error code on failure.
+ */
+int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
+			int active)
+{
+	struct snd_kcontrol *kctl;
+	struct snd_kcontrol_volatile *vd;
+	unsigned int index_offset;
+	int ret;
+
+	down_write(&card->controls_rwsem);
+	kctl = snd_ctl_find_id(card, id);
+	if (kctl == NULL) {
+		up_write(&card->controls_rwsem);
+		return -ENOENT;
+	}
+	index_offset = snd_ctl_get_ioff(kctl, &control->id);
+	vd = &kctl->vd[index_offset];
+	ret = 0;
+	if (active) {
+		if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE))
+			goto unlock;
+		vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+	} else {
+		if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)
+			goto unlock;
+		vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+	}
+	ret = 1;
+ unlock:
+	up_write(&card->controls_rwsem);
+	if (ret)
+		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
+	return ret;
+}
+EXPORT_SYMBOL(snd_ctl_activate_id);
+
+/**
  * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it
  * @file: active control handle
  * @id: the control id to remove


More information about the Alsa-devel mailing list