On Sun, Aug 30, 2009 at 09:35:08PM -0400, Ryan Flannery wrote:
> On Sun, Aug 30, 2009 at 8:55 PM, Brynet<bry...@gmail.com> wrote:
> > Edd wrote:
> >> Upon invocation I get:
> >> xstatbar: ioctl AUDIO_MIXER_READ: Invalid argument
> >
> > The system I was using had no sound card.. I assumed this error was
> > related to that, so perhaps the author can tell us why it doesn't
> > work?
> >
> > Here is the cosmetic changes anyway, sorry for not properly testing.
> >
> 
> Off-hand I have no idea why this fails, but I can dig into it further
> if it is still an open issue.

couple issues here ...

   /* find the "master" device */
   v->master_idx = -1;
   devinfo.index = 0;
   while (ioctl(v->dev_fd, AUDIO_MIXER_DEVINFO, &devinfo) >= 0)
   {  if (strncmp(devinfo.label.name, "master", 7) == 0)
         v->master_idx = devinfo.index;

      devinfo.index++;
   }

   if (v->master_idx == -1)
      errx(1, "failed to find \"master\" mixer device for volume init");

you should make sure you get outputs.master as opposed to possibly
record.master, or some other "master".  technically speaking, a device
is free to make up whatever class it wants.  you have to find the
"outputs" class index, and make sure that "master"'s mixer_class equals
the "outputs" class index.

   /* Volume values are stored as 8-bit values, however not all values are
    * supported (i.e. fewer than 256 different volume levels may be
    * supported).  As such, to accurately determine the percentages shown
    * in the display, we have to find the maximum settings for this
    * device.

you could use the delta: devinfo.un.v.delta.  that is the step size
of the hardware.  that is, you have to move that many volume units to
affect a change in the hardware.  you could use this to determine
the largest value ...

  So, we...
    *    1. read the current volume values
    *    2. set the volume to the max possible (255)

255 -> AUDIO_MAX_GAIN

    *    3. read the volume values and see what the max is for this device
    *    4. reset the volume to what was read in step 1 so we don't muck
    *       with the users' volume.
    */

   /* read current volume */
   v->info.dev = v->master_idx;
   v->info.type = AUDIO_MIXER_VALUE;
   if (ioctl(v->dev_fd, AUDIO_MIXER_READ, &(v->info)) < 0)
      err(1, "ioctl AUDIO_MIXER_READ");

that fails because on many devices because num_channels is not set
correctly.  in sys/dev/ic/ac97.c:

ac97_mixer_get_port(struct ac86_codec_if *codec_if, mixer_ctrl_t *cp)
{
        struct ac97_softc *as = (struct ac97_softc *)codec_if;
        struct ac97_source_info *si = &as->source_info[cp->dev];
...
        case AUDIO_MIXER_VALUE:
        {
                const struct audio_mixer_value *value = si->info;
                u_int16_t  l, r;

                if ((cp->un.value.num_channels <= 0) ||
                    (cp->un.value.num_channels > value->num_channels))
                        return (EINVAL);

here, value->num_channels == devinfo.un.v.num_channels ...

-- 
jake...@sdf.lonestar.org
SDF Public Access UNIX System - http://sdf.lonestar.org

Reply via email to