typedef struct _selem_ctl {
snd_hctl_elem_t *elem;
snd_ctl_elem_type_t type;
+ unsigned int access;
unsigned int values;
long min, max;
} selem_ctl_t;
simple = melem->private_data;
ctl = &simple->ctls[CTL_SINGLE];
if (ctl->elem) {
- pchannels = ctl->values;
+ pchannels = cchannels = ctl->values;
if (ctl->type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
- caps |= CAP_GVOLUME | CAP_PVOLUME;
- pmin = ctl->min;
- pmax = ctl->max;
+ caps |= CAP_GVOLUME;
+ pmin = cmin = ctl->min;
+ pmax = cmax = ctl->max;
} else
- caps |= CAP_GSWITCH | CAP_PSWITCH;
+ caps |= CAP_GSWITCH;
}
ctl = &simple->ctls[CTL_GLOBAL_SWITCH];
if (ctl->elem) {
pchannels = ctl->values;
if (cchannels < ctl->values)
cchannels = ctl->values;
- caps |= CAP_GSWITCH | CAP_PSWITCH;
+ caps |= CAP_GSWITCH;
}
ctl = &simple->ctls[CTL_GLOBAL_ROUTE];
if (ctl->elem) {
pchannels = ctl->values;
if (cchannels < ctl->values)
cchannels = ctl->values;
- caps |= CAP_GSWITCH | CAP_PSWITCH;
+ caps |= CAP_GSWITCH;
}
ctl = &simple->ctls[CTL_GLOBAL_VOLUME];
if (ctl->elem) {
cmin = ctl->min;
if (cmax < ctl->max)
cmax = ctl->max;
- caps |= CAP_GVOLUME | CAP_PVOLUME;
+ caps |= CAP_GVOLUME;
}
ctl = &simple->ctls[CTL_PLAYBACK_SWITCH];
if (ctl->elem) {
if (pchannels < ctl->values)
pchannels = ctl->values;
caps |= CAP_PSWITCH;
+ caps &= ~CAP_GSWITCH;
}
ctl = &simple->ctls[CTL_PLAYBACK_ROUTE];
if (ctl->elem) {
if (pchannels < ctl->values)
pchannels = ctl->values;
caps |= CAP_PSWITCH;
+ caps &= ~CAP_GSWITCH;
}
ctl = &simple->ctls[CTL_CAPTURE_SWITCH];
if (ctl->elem) {
if (pmax < ctl->max)
pmax = ctl->max;
caps |= CAP_PVOLUME;
+ caps &= ~CAP_GVOLUME;
}
ctl = &simple->ctls[CTL_CAPTURE_VOLUME];
if (ctl->elem) {
pchannels = 32;
if (cchannels > 32)
cchannels = 32;
- if (caps & CAP_PSWITCH)
+ if (caps & (CAP_GSWITCH|CAP_PSWITCH))
caps |= CAP_PSWITCH_JOIN | CAP_PVOLUME_JOIN;
- if (caps & CAP_CSWITCH)
+ if (caps & (CAP_GSWITCH|CAP_CSWITCH))
caps |= CAP_CSWITCH_JOIN | CAP_PVOLUME_JOIN;
if (pchannels > 1 || cchannels > 1) {
if (simple->ctls[CTL_SINGLE].elem &&
if (simple->ctls[CTL_GLOBAL_ROUTE].elem ||
(simple->ctls[CTL_GLOBAL_SWITCH].elem &&
simple->ctls[CTL_GLOBAL_SWITCH].values > 1)) {
- caps &= ~CAP_PSWITCH_JOIN;
+ caps &= ~(CAP_PSWITCH_JOIN|CAP_CSWITCH_JOIN);
}
if (simple->ctls[CTL_GLOBAL_VOLUME].elem &&
simple->ctls[CTL_GLOBAL_VOLUME].values > 1) {
- caps &= ~CAP_PVOLUME_JOIN;
+ caps &= ~(CAP_PVOLUME_JOIN|CAP_CVOLUME_JOIN);
}
}
if (pchannels > 1) {
assert(!simple->ctls[type].elem);
simple->ctls[type].elem = helem;
simple->ctls[type].type = info.type;
+ simple->ctls[type].access = info.access;
simple->ctls[type].values = info.count;
simple->ctls[type].min = info.value.integer.min;
simple->ctls[type].max = info.value.integer.max;
return snd_mixer_elem_info(melem);
}
-static int simple_event_info(snd_mixer_elem_t *melem)
-{
- int err = simple_update(melem);
- assert(err >= 0);
- return snd_mixer_elem_info(melem);
-}
-
static int simple_event(snd_mixer_class_t *class, unsigned int mask,
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
{
return err;
}
if (mask & SND_CTL_EVENT_MASK_INFO) {
- err = simple_event_info(melem);
+ err = simple_event_remove(helem, melem);
+ if (err < 0)
+ return err;
+ err = simple_event_add(class, helem);
if (err < 0)
return err;
+ return 0;
}
if (mask & SND_CTL_EVENT_MASK_VALUE) {
err = selem_read(melem);
return p;
}
+/**
+ * \brief Get info about the active state of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \return 0 if not active, 1 if active
+ */
+int snd_mixer_selem_is_active(snd_mixer_elem_t *elem)
+{
+ selem_t *s;
+ selem_ctl_type_t ctl;
+ assert(elem);
+ assert(elem->type == SND_MIXER_ELEM_SIMPLE);
+ s = elem->private_data;
+ for (ctl = CTL_SINGLE; ctl <= CTL_LAST; ctl++)
+ if (s->ctls[ctl].elem != NULL && (s->ctls[ctl].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != 0)
+ return 0;
+ return 1;
+}
+
/**
* \brief Get info about channels of playback stream of a mixer simple element
* \param elem Mixer simple element handle
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- return !!(s->caps & CAP_PVOLUME);
+ return !!(s->caps & CAP_PVOLUME) || !!(s->caps & CAP_GVOLUME);
}
/**
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- return !!(s->caps & CAP_PSWITCH);
+ return !!(s->caps & CAP_PSWITCH) && !!(s->caps & CAP_GSWITCH);
}
/**
*/
int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
{
- int err;
selem_t *s;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
assert((unsigned int) channel < s->str[PLAY].channels);
- assert(s->caps & CAP_PVOLUME);
- err = snd_mixer_handle_events(elem->class->mixer);
- if (err < 0)
- return err;
+ assert(s->caps & (CAP_PVOLUME|CAP_GVOLUME));
if (s->caps & CAP_PVOLUME_JOIN)
channel = 0;
*value = s->str[PLAY].vol[channel];
*/
int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
{
- int err;
selem_t *s;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
assert((unsigned int) channel < s->str[PLAY].channels);
- assert(s->caps & CAP_PSWITCH);
- err = snd_mixer_handle_events(elem->class->mixer);
- if (err < 0)
- return err;
+ assert(s->caps & (CAP_PSWITCH|CAP_GSWITCH));
if (s->caps & CAP_PSWITCH_JOIN)
channel = 0;
*value = !!(s->str[PLAY].sw & (1 << channel));
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- assert(s->caps & CAP_PVOLUME);
+ assert(s->caps & (CAP_GVOLUME|CAP_PVOLUME));
changed = _snd_mixer_selem_set_volume(elem, PLAY, channel, value);
if (changed < 0)
return changed;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- assert(s->caps & CAP_PVOLUME);
+ assert(s->caps & (CAP_GVOLUME|CAP_PVOLUME));
changed = _snd_mixer_selem_set_volume_all(elem, PLAY, value);
if (changed < 0)
return changed;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- assert(s->caps & CAP_PSWITCH);
+ assert(s->caps & (CAP_GSWITCH|CAP_PSWITCH));
changed = _snd_mixer_selem_set_switch(elem, PLAY, channel, value);
if (changed < 0)
return changed;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- assert(s->caps & CAP_PSWITCH);
+ assert(s->caps & (CAP_GSWITCH|CAP_PSWITCH));
changed = _snd_mixer_selem_set_switch_all(elem, PLAY, value);
if (changed < 0)
return changed;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- return !!(s->caps & CAP_CVOLUME);
+ return !!(s->caps & CAP_CVOLUME) || !!(s->caps & CAP_GVOLUME);
}
/**
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- return !!(s->caps & CAP_CSWITCH);
+ return !!(s->caps & CAP_CSWITCH) || !!(s->caps & CAP_GSWITCH);
}
/**
*/
int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
{
- int err;
selem_t *s;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
assert((unsigned int) channel < s->str[CAPT].channels);
- assert(s->caps & CAP_CVOLUME);
- err = snd_mixer_handle_events(elem->class->mixer);
- if (err < 0)
- return err;
+ assert(s->caps & (CAP_GVOLUME|CAP_CVOLUME));
if (s->caps & CAP_CVOLUME_JOIN)
channel = 0;
*value = s->str[CAPT].vol[channel];
*/
int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
{
- int err;
selem_t *s;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
assert((unsigned int) channel < s->str[CAPT].channels);
- assert(s->caps & CAP_CSWITCH);
- err = snd_mixer_handle_events(elem->class->mixer);
- if (err < 0)
- return err;
+ assert(s->caps & (CAP_GSWITCH | CAP_CSWITCH));
if (s->caps & CAP_CSWITCH_JOIN)
channel = 0;
*value = !!(s->str[CAPT].sw & (1 << channel));
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- assert(s->caps & CAP_CVOLUME);
+ assert(s->caps & (CAP_GVOLUME | CAP_CVOLUME));
changed = _snd_mixer_selem_set_volume(elem, CAPT, channel, value);
if (changed < 0)
return changed;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- assert(s->caps & CAP_CVOLUME);
+ assert(s->caps & (CAP_GVOLUME | CAP_CVOLUME));
changed = _snd_mixer_selem_set_volume_all(elem, CAPT, value);
if (changed < 0)
return changed;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- assert(s->caps & CAP_CSWITCH);
+ assert(s->caps & (CAP_GSWITCH | CAP_CSWITCH));
changed = _snd_mixer_selem_set_switch(elem, CAPT, channel, value);
if (changed < 0)
return changed;
assert(elem);
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
s = elem->private_data;
- assert(s->caps & CAP_CSWITCH);
+ assert(s->caps & (CAP_GSWITCH | CAP_CSWITCH));
changed = _snd_mixer_selem_set_switch_all(elem, CAPT, value);
if (changed < 0)
return changed;