Subject: problem setting record.source via OSS interface
To: None <netbsd-help@netbsd.org>
From: Brook Milligan <brook@biology.nmsu.edu>
List: netbsd-help
Date: 01/26/2006 16:10:17
NetBSD audio wizards,

I am trying to set the record.source mixer property via the OSS
interface to the NetBSD audio system.  The ioctls appear to work, but
they set the mixer property incorrectly.  For example, here is a table
of how the argument to the SOUND_MIXER_WRITE_RECSRC ioctl maps into
its effect on the record.source device reported by mixerctl(1):

   ioctl          OSS         mixerctl(1)
argument  device name              output
-----------------------------------------
       6         line  record.source=line
       7          mic  record.source=cd
      14        line1  record.source=aux

Clearly, the OSS device name corresponding to the argument does not
agree with the actual effect as reported by mixerctl(1).

The program that generated this information is given below, followed
by its complete output.

I would appreciate help in identifying the problem.  Thank you very
much.

Cheers,
Brook

===========================================================================
#include <sys/ioctl.h>
#include <err.h>
#include <fcntl.h>
#include <soundcard.h>
#include <stdio.h>
#include <stdlib.h>

const char* sound_device_names[] = SOUND_DEVICE_NAMES;

int
main ()
{
  const char* mixer = "/dev/mixer";
  int fd;
  int rec_mask;
  int rec_src;
  int i;

  /* open mixer device */
  fd = open (mixer, O_RDWR, O_NONBLOCK);
  if (fd < 0)
    err(1, "cannot open %s", mixer);

  /* recording input mask */
  if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &rec_mask) != 0)
    err(1, "cannot read record input mask");
  printf("record input mask:  0x%08x\n", rec_mask);
  for (i = 0; i < 32; ++i)
    {
      rec_src = 1 << i;
      if (rec_mask & rec_src)
	{
	  printf ("%2d. 0x%08x  %8s\n",
		  i, (rec_mask & rec_src), sound_device_names[i]);
	}
    }
  printf ("\n");

  /* set recording input */
  printf("setting record input:\n");
  for (i = 0; i < 32; ++i)
    {
      rec_src = 1 << i;
      if (rec_mask & rec_src)
	{
	  printf ("%2d. 0x%08x  %8s  ",
		  i, (rec_mask & rec_src), sound_device_names[i]);
	  fflush(stdout);
	  if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &rec_src) != 0)
	    err(1, "cannot set record input source");
	  system ("mixerctl record.source");
	  fflush(stdout);
	}
    }
  printf ("\n");

  return 0;
}
===========================================================================
#   compile  test/test.o
cc -O2   -Werror      -c    test.c
#      link  test/test
cc    -o test  -Wl,-rpath-link,/lib:/usr/lib  -L/lib test.o -lossaudio 
./test
record input mask:  0x000040c0
 6. 0x00000040      line
 7. 0x00000080       mic
14. 0x00004000     line1

setting record input:
 6. 0x00000040      line  record.source=line
 7. 0x00000080       mic  record.source=cd
14. 0x00004000     line1  record.source=aux
===========================================================================