[alsa-devel] get rid of controls with snd_ctl_remove

Takashi Iwai tiwai at suse.de
Fri Aug 29 15:41:21 CEST 2008


At Fri, 29 Aug 2008 14:16:52 +0100,
Liam Girdwood wrote:
> 
> On Fri, 2008-08-29 at 15:01 +0200, Takashi Iwai wrote:
> > At Fri, 29 Aug 2008 14:54:42 +0200,
> > Harald Radke wrote:
> > > 
> > > Hi there!
> > > 
> > > Please be patient with me, I am quite inexperienced with alsa programming, so 
> > > this might be a dumb question:
> > > 
> > > We have a WM8750 working in our PDA, the codec is working so far but I want to 
> > > remove some of the control since they aren't needed.
> > > 
> > > Instead of copying the wm8750.c file and adjusting it, I want to write another 
> > > module which basically get rid of those controls, something like:
> > > 
> > > [...]
> > > 
> > > static const char* unused_controls[] = {"AAAA", "BBBB,"CCCC"};
> > > 
> > >         struct snd_kcontrol *ctl;
> > > 
> > >         list_for_each_entry(ctl, &card->controls, list)
> > 
> > You can't use list_for_each_entry() together with removal.
> > Use list_for_each_entry_safe() for such a purpose.
> > 
> > But...
> > 
> > >           for(i=0; i <  ARRAY_SIZE(unused_controls); i++)
> > >             if (!strcmp(unused_controls[i],ctl->id.name)) {
> > >               down_write(&card->controls_rwsem);
> > >               snd_ctl_remove(card,ctl);
> > >               up_write(&card->controls_rwsem);
> > >               break;
> > >             }
> > 
> > It'd be easier like the following:
> > 
> > 	for (i = 0; i < ARRAY_SIZE(unused_controls); i++) {
> > 		struct snd_ctl_elem_id id;
> > 		memset(&id, 0, sizeof(id));
> > 		strcpy(id.name, unused_controls[i]);
> > 		id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
> > 		snd_ctl_remove_id(card, &id);
> > 	}
> 
> 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


More information about the Alsa-devel mailing list