[alsa-devel] Softvol controls

John Utz john.utz at dmx.com
Fri Nov 30 00:46:57 CET 2007


Hi Lennart!

On Fri, 30 Nov 2007 00:28:59 +0100
"Lennart Poettering" <mznyfn at 0pointer.de> wrote:

> On Wed, 21.11.07 12:22, Takashi Iwai (tiwai at suse.de) wrote:
> 
> > >    Now, is there a way I can detect for a mixer element if it is
> > >    "real" or if it is implemented only for the "plughw" PCM? As it
> > >    seems the "hw:0" mixer device does contain "virtual" tracks,
> > > isn't that a bit strange? Shouldn't the virtual mixer tracks be
> > > available only in a mixer device "plughw:0"? That at least would
> > > be symmetric to the PCM case, wouldn't it?
> > 
> > Check snd_ctl_elem_info_is_user().  All softvol controls are
> > implemented as user elements.
> 
> Hmm, how am I supposed to get the snd_ctl_elem_info_t from a
> snd_mixer_elem_t or snd_mixer_selem_id_t?
> 
> I figure there is no useful documentation or even example how this is
> supposed to work? Hmm, is there any real documentation available which
> describes the relation of ctl, hctl, mixer and smixer at all? For the
> uninitated the whols structure looks overly complex and redundant.

Here's my take on it....HTH

dont hesitate to ask


// ALSA Mixer creation and manipulation routines
//
// The alsa api is pretty cool once you find a working example :-)
//  
// One first creates the mixer representation and then 1 element
// representation for each item that you need to manipulate.
// create the individual elements, ie PCM, Surround, etc

snd_mixer_elem_t *
alsa_mixer_elem_instantiate(char *pNameElem, snd_mixer_t *pSndMxr)
{
  char  acLog[256] = "";
  int    iErr      = 0;

  snd_mixer_elem_t      *pSndMxrElem;
  snd_mixer_selem_id_t  *pSndMxrSlem;

  snd_mixer_selem_id_alloca(&pSndMxrSlem);
  snd_mixer_selem_id_set_name(pSndMxrSlem, pNameElem);

  sprintf(acLog, "Initializing ALSA Mixer Element: %s", pNameElem);
  aeiu_logprint("PC18", AEIU_LOG_INFO, acLog);

  // find element based on name

  if(!(pSndMxrElem=snd_mixer_find_selem(pSndMxr, pSndMxrSlem))) goto
fin;

  // make sure they are turned on so we can hear them, not always the
case

  aeiu_logprint("PC19", AEIU_LOG_INFO, "ALSA Mixer Element Enable"  );
  if(snd_mixer_selem_has_playback_switch(pSndMxrElem))
    if((iErr=snd_mixer_selem_set_playback_switch_all(pSndMxrElem, 1)))
      goto fin;

  // configure them for the old style 0-100 oss volume range

  aeiu_logprint("PC20", AEIU_LOG_INFO, "ALSA Mixer Element Set
Range"  );

  if((iErr=snd_mixer_selem_set_playback_volume_range(pSndMxrElem, 0,
100))) goto fin;

  // set to a reasonable starting value

  aeiu_logprint("PC21", AEIU_LOG_INFO, "ALSA Mixer Element Set
Volume"  );

  if((iErr=snd_mixer_selem_set_playback_volume_all(pSndMxrElem, 65)))
goto fin;

 fin:

  if(!pSndMxrElem || iErr)
  {
    sprintf(acLog,"alsa_mixer_elem_instantiate: %s Failed: %s\n",
pNameElem, iErr ? snd_strerror(iErr) : "Mixer Device Not Found");
    aeiu_logprint("PC22", AEIU_LOG_ERROR, acLog);
  }

  return pSndMxrElem;
}


int
alsa_mixer_instantiate()
{
  int    iErr        = 0;
  char *pcNameDevMxr = "default";

  aeiu_logprint("PC23", AEIU_LOG_INFO, "Initializing ALSA Mixer");

  if(gpSndMxr)
  {
    aeiu_logprint("PC24", AEIU_LOG_ERROR,"alsa_mixer_instantiate:
pSndMxr!=NULL"); iErr=1;
    goto fin;
  }

  if((iErr = snd_mixer_open(&gpSndMxr, 0)))                   goto fin;

  if((iErr = snd_mixer_attach(gpSndMxr, pcNameDevMxr)))       goto fin;
   
  if((iErr = snd_mixer_selem_register(gpSndMxr, NULL, NULL))) goto fin;

  if((iErr = snd_mixer_load(gpSndMxr)))                       goto fin;

  // mixer device is now live, create the control elements, note that
  // we dont error check here because we do it in the function and we
  // dont want to break execution flow here if we fail for some reason
  // (rather have 2 channels than no channels!)

  gpSndMxrElemCrdV = alsa_mixer_elem_instantiate("PCM",      gpSndMxr);

  gpSndMxrElemCrd0 = alsa_mixer_elem_instantiate("Master",   gpSndMxr);
 
  gpSndMxrElemCrd1 = alsa_mixer_elem_instantiate("Surround", gpSndMxr);

  // this exists only for a function called pcm_lowervolumes()

  gpSndMxrElemCrdM = alsa_mixer_elem_instantiate("Mic",      gpSndMxr);

fin:

  if(iErr)
  {
    if(gpSndMxr)
    {
      snd_mixer_close(gpSndMxr);
      gpSndMxr = NULL;
    }

    char  acLog[256] = "";
    sprintf(acLog, "alsa_mixer_instantiate: Failed: %s",
snd_strerror(iErr)); aeiu_logprint("PC25", AEIU_LOG_ERROR, acLog);
  }
  return iErr;
}




> Lennart
> 



More information about the Alsa-devel mailing list