diff options
Diffstat (limited to 'tutorials/sndkit/samples/mixext.c')
-rw-r--r-- | tutorials/sndkit/samples/mixext.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/tutorials/sndkit/samples/mixext.c b/tutorials/sndkit/samples/mixext.c new file mode 100644 index 0000000..a70e638 --- /dev/null +++ b/tutorials/sndkit/samples/mixext.c @@ -0,0 +1,270 @@ +/* + * Purpose: A simple sample program for using the new mixer API + * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL. + * + * Description: + * This program is as simple as possible example for using the new mixer API + * of OSS 4.0 (and later) from applications. It shows how to read or + * change the settings. Please read the OSS API Developer's Manual for + * more info about this API. + * + * This mixer interface is designed to ne "human readable". The idea is that + * the mixer program just shows whatever controls are available and lets the + * user to adjust them as he/she likes. + * + * Please note that the control names and numbers are fully dynamic. There are + * some control names such as "spdif.enable" that are used by several different + * drivers. It's relatively safe to assume that such controls have always + * the same meaning. However there is no list of such control names + * available at this moment. Even this kind of controls are supported just by + * some of the devices (some devices just don't have that feature). + * + * Most control names are 100% non-portable between devices. In addition some + * settings may be available depending on the configuration. + * + * {!notice Applications using this mixer interface must not assume that + * certain controls are always available or that they have exactly defined + * meanings.} + * + * This program can be run without any command line arguments to + * list the available controls and their values. The mixer device number + * (0 by default) can be given on the command line. + * + * Another way is to give the mixer number, control ame and value + * on the command line ({!shell mixext 1 spdif.enable 1}). + */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <soundcard.h> +#include <time.h> +#include <errno.h> + +static int mixer_dev = 0; /* Change this to access another mixer device */ +static int mixerfd = -1; + +typedef struct +{ + int num; + char *name; +} name_ent; + +#define TYPE_ENTRY(x) {x, #x} + +name_ent type_names[] = { + TYPE_ENTRY (MIXT_DEVROOT), + TYPE_ENTRY (MIXT_GROUP), + TYPE_ENTRY (MIXT_ONOFF), + TYPE_ENTRY (MIXT_MUTE), + TYPE_ENTRY (MIXT_ENUM), + TYPE_ENTRY (MIXT_MONOSLIDER), + TYPE_ENTRY (MIXT_STEREOSLIDER), + TYPE_ENTRY (MIXT_MESSAGE), + TYPE_ENTRY (MIXT_MONOVU), + TYPE_ENTRY (MIXT_STEREOVU), + TYPE_ENTRY (MIXT_MONOPEAK), + TYPE_ENTRY (MIXT_STEREOPEAK), + TYPE_ENTRY (MIXT_RADIOGROUP), + TYPE_ENTRY (MIXT_MARKER), + TYPE_ENTRY (MIXT_VALUE), + TYPE_ENTRY (MIXT_HEXVALUE), + TYPE_ENTRY (MIXT_MONODB), + TYPE_ENTRY (MIXT_STEREODB), + TYPE_ENTRY (MIXT_SLIDER), + TYPE_ENTRY (MIXT_3D), + TYPE_ENTRY (MIXT_MONOSLIDER16), + TYPE_ENTRY (MIXT_STEREOSLIDER16), + {-1, NULL} +}; + +static char * +mixt_name (int num) +{ + int i; + + i = 0; + + while (type_names[i].num != -1) + { + if (type_names[i].num == num) + return type_names[i].name; + i++; + } + return "Unknown type"; +} + +void +list_controls (int mixer_dev) +{ + int i, n, nn = 0; + oss_mixext ext; + int marker_seen = 0; + + n = mixer_dev; + + if (ioctl (mixerfd, SNDCTL_MIX_NREXT, &n) == -1) + { + perror ("SNDCTL_MIX_NREXT"); + if (errno == EINVAL) + fprintf (stderr, "Error: OSS version 3.9 or later is required\n"); + return; + } + + printf ("%d mixer controls available (including ordinary mixer controls)\n", + n); + + for (i = 0; i < n; i++) + { + oss_mixer_value val; + + ext.dev = mixer_dev; + ext.ctrl = i; + + if (ioctl (mixerfd, SNDCTL_MIX_EXTINFO, &ext) == -1) + { + if (errno == EINVAL) + { + fprintf (stderr, "SNDCTL_MIX_EXTINFO failed\n"); + fprintf (stderr, + "This is almost certainly caused by a too old or new OSS version.\n"); + return; + } + + perror ("SNDCTL_MIX_EXTINFO"); + return; + } + + if (ext.type == MIXT_MARKER) + { + marker_seen = 1; + continue; + } + else if (!marker_seen) + continue; + + val.dev = mixer_dev; + val.ctrl = i; + val.timestamp = ext.timestamp; + + val.value = 0; + + if (ext.type != MIXT_DEVROOT && ext.type != MIXT_GROUP + && ext.type != MIXT_MARKER) + if (ioctl (mixerfd, SNDCTL_MIX_READ, &val) == -1) + { + perror ("SNDCTL_MIX_READ"); + val.value = 0xffffffff; + } + + printf ("%3d: \"%s\" (\"%s\"), parent %d\n", i, ext.extname, ext.id, + ext.parent); + printf (" Type %d (%s), value %d (0x%08x) (max %d)\n", ext.type, + mixt_name (ext.type), val.value, val.value, ext.maxvalue); + printf (" Update counter %d\n", ext.update_counter); + nn++; + } + + printf ("%d controls accessible by this program\n", nn); +} + +int +set_control (int mixer_dev, char *name, int value) +{ + int i, n; + oss_mixext ext; + int marker_seen = 0; + + n = mixer_dev; + + if (ioctl (mixerfd, SNDCTL_MIX_NREXT, &n) == -1) + { + perror ("SNDCTL_MIX_NREXT"); + if (errno == EINVAL) + fprintf (stderr, "Error: OSS version 3.9 or later is required\n"); + return -4; + } + + for (i = 0; i < n; i++) + { + oss_mixer_value val; + + ext.dev = mixer_dev; + ext.ctrl = i; + + if (ioctl (mixerfd, SNDCTL_MIX_EXTINFO, &ext) == -1) + { + perror ("SNDCTL_MIX_EXTINFO"); + return -1; + } + + if (ext.type == MIXT_MARKER) + { + marker_seen = 1; + continue; + } + else if (!marker_seen) + continue; + + + if (strcmp (ext.extname, name) != 0) /* No match */ + continue; + + if (!(ext.flags & MIXF_WRITEABLE)) + return -2; + + val.dev = mixer_dev; + val.ctrl = i; + val.timestamp = ext.timestamp; + val.value = value; + + if (ioctl (mixerfd, SNDCTL_MIX_WRITE, &val) == -1) + { + perror ("SNDCTL_MIX_WRITE"); + return -3; + } + + return 1; + } + + return 0; +} + +int +main (int argc, char *argv[]) +{ + char *devmixer; + + if ((devmixer=getenv("OSS_MIXERDEV"))==NULL) + devmixer = "/dev/mixer"; + + if (argc > 1) + mixer_dev = atoi (argv[1]); + + if ((mixerfd = open (devmixer, O_RDWR, 0)) == -1) + { + perror (devmixer); + exit (-1); + } + + if (argc > 3) + { + int val; + + val = atoi (argv[3]); + + if (set_control (mixer_dev, argv[2], val) > 0) + { + fprintf (stderr, "OK\n"); + } + else + { + fprintf (stderr, "Failed!!!\n"); + } + exit (0); + } + + list_controls (mixer_dev); + + exit (0); +} |