Subject: Re: mixer?
To: Brandon Reed <reed@reedb.rhn.orst.edu>
From: Rolf Grossmann <grossman@informatik.tu-muenchen.de>
List: current-users
Date: 04/21/1995 00:17:21
Hi,
on Tue, 11 Apr 1995 06:41:42 +0200 Brandon Reed wrote
concerning "Re: mixer?" something like this:
>> > ie: can I do something like:
>> > echo volume=50 > /dev/mixer ??
>> > It makes sense to me.
>>
>> No, you can't. And although it might be quite nice, I don't think we would
>> like to have code for parsing this stuff inside the kernel. It really isn't
>> that hard to write C code to do that stuff.
> any samples floating around?
> how about a mixer binary (stick it in as a small file in /usr/bin or
> somewhere more appropriate ) that calls the mixer device and performs
> the basic functions like main volume/gain/etc. If the mixer i/o is the same
> on every platform it should be pretty standard, or if the io controls
> are system dependent add it to the kernel make so that when someone
> selects the audio device in their config it's automgaically produced for
> their enjoyment. it doesn't have to be
> pretty just functional If you use a well-defined set of codes it should
> be exremely easy to parse. If people want some nifty X based applet they
> can get one somewhere else. I don't think I should need to write my own
> program just to turn down the volume.
> Was there any functionality for this in the 1.0 soundblaster code?
> I never used it so I don't know.
[...]
> If someone can produce simple code other people can make it fancy later.
Ok, I finally had the time and the need to code something up, that is generic
enough to work on all platforms while being functional enough to be a good
example. It follows the basic idea outlined above, while interpreting the
mixer interface the way the code suggests (as there is no documentation).
It's not yet 100% complete, but it should get you going it you're desperate.
I'll try to get a complete version into the tree, once I've done it.
If you have any questions about the usage or have any problems, feel free to
ask.
Bye, Rolf
----------------------------- mixer.c ---------------------------------
/* $NetBSD$ */
/*
* Copyright (c) 1995 Rolf Grossmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Rolf Grossmann.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/audioio.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#include <fcntl.h>
#include <db.h>
DB *
get_devinfo(int mixer)
{
DB *dev_db;
DBT key, data;
mixer_devinfo_t di;
dev_db = dbopen(NULL, O_RDWR|O_CREAT, 0666, DB_HASH, NULL);
if (dev_db == NULL)
err(1, "open database");
di.index = 0;
while (ioctl(mixer, AUDIO_MIXER_DEVINFO, &di) == 0)
{
key.data = di.label.name;
key.size = strlen(di.label.name);
data.data = &di;
data.size = sizeof(di);
if (dev_db->put(dev_db, &key, &data, 0) != 0)
err(1, "build database");
di.index++;
}
return dev_db;
}
int
main(int argc, char *argv[])
{
int mixer;
DB *dev_db;
DBT key, data;
mixer_devinfo_t dvinfo;
mixer_ctrl_t ctl;
int i, v;
char *p;
mixer = open("/dev/mixer", O_RDONLY, 0); /* XXX define _PATH_MIXER ? */
if (mixer < 0)
err(1, "Can't open mixer device");
dev_db = get_devinfo(mixer);
if (argc == 1)
{
extern const char *__progname;
fprintf(stderr, "usage: %s {name | name=value}*\n", __progname);
fprintf(stderr, "Possible names are:\n");
while (dev_db->seq(dev_db, &key, &data, R_NEXT) == 0)
{
bcopy(data.data, &dvinfo, sizeof(dvinfo));
if (dvinfo.type == AUDIO_MIXER_VALUE) /* XXX */
fprintf(stderr, "%s\n", key.data);
}
exit(1);
}
for (i = 1; i < argc; i++)
{
p = strsep(&argv[i], "=");
key.data = p;
key.size = strlen(p);
if ((v = dev_db->get(dev_db, &key, &data, 0)) != 0)
{
if (v == 1)
{
warnx("%s is not a valid audio name.", p);
continue;
}
else
err(1, "key lookup failed");
}
bcopy(data.data, &dvinfo, sizeof(dvinfo));
if (argv[i] != NULL)
{
/* set value */
if (dvinfo.type != AUDIO_MIXER_VALUE)/* XXX also do other types */
{
warnx("%s is not a settable value.", p);
continue;
}
v = atoi(argv[i]);
if (v < 0 || v > 255)
{
warnx("value %d out of range ([0..255]). %s not set.", v, p);
continue;
}
ctl.dev = dvinfo.index;
ctl.type = AUDIO_MIXER_VALUE;
ctl.un.value.num_channels = 1;
ctl.un.value.level[0] = v;
if (ioctl(mixer, AUDIO_MIXER_WRITE, &ctl) != 0)
warnx("setting %s to %d failed.", p, v);
} else {
/* read value */
if (dvinfo.type != AUDIO_MIXER_VALUE)/* XXX also do other types */
{
warnx("%s is not a settable value.", p);
continue;
}
ctl.dev = dvinfo.index;
ctl.type = AUDIO_MIXER_VALUE;
ctl.un.value.num_channels = 1;
if (ioctl(mixer, AUDIO_MIXER_READ, &ctl) != 0)
warnx("reading value for %s failed.", p);
else
printf("%s=%u\n", p, ctl.un.value.level[0]);
}
}
return(0);
}