198 lines
5.3 KiB
C
198 lines
5.3 KiB
C
|
// mixctl.h - MixCtl class provides control of audio mixer functions
|
||
|
// 05/09/98 Release 1.0 Beta1
|
||
|
// Copyright (C) 1998 Sam Hawker <shawkie@geocities.com>
|
||
|
// This software comes with ABSOLUTELY NO WARRANTY
|
||
|
// This software is free software, and you are welcome to redistribute it
|
||
|
// under certain conditions
|
||
|
// See the COPYING file for details.
|
||
|
|
||
|
// Although mixctl.h is an integral part of wmmixer, it may also be distributed seperately.
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <unistd.h>
|
||
|
#ifdef __NetBSD__
|
||
|
#include <soundcard.h>
|
||
|
#endif
|
||
|
#ifdef __FreeBSD__
|
||
|
#include <machine/soundcard.h>
|
||
|
#endif
|
||
|
#ifdef __linux__
|
||
|
#include <linux/soundcard.h>
|
||
|
#endif
|
||
|
|
||
|
class MixCtl
|
||
|
{
|
||
|
public:
|
||
|
MixCtl(char *dname){
|
||
|
device=(char *)malloc(sizeof(char)*(strlen(dname)+1));
|
||
|
strcpy(device,dname);
|
||
|
if(mixfdopen=(mixfd=open(device,O_RDONLY | O_NONBLOCK))!=-1){
|
||
|
nrdevices=SOUND_MIXER_NRDEVICES;
|
||
|
char *devnames[]=SOUND_DEVICE_NAMES;
|
||
|
char *devlabels[]=SOUND_DEVICE_LABELS;
|
||
|
ioctl(mixfd, SOUND_MIXER_READ_DEVMASK, &devmask);
|
||
|
ioctl(mixfd, SOUND_MIXER_READ_STEREODEVS, &stmask);
|
||
|
ioctl(mixfd, SOUND_MIXER_READ_RECMASK, &recmask);
|
||
|
ioctl(mixfd, SOUND_MIXER_READ_CAPS, &caps);
|
||
|
mixdevs=(struct MixDev *)malloc(sizeof(struct MixDev)*nrdevices);
|
||
|
int mixmask=1;
|
||
|
for(int i=0;i<nrdevices;i++){
|
||
|
mixdevs[i].support=devmask & mixmask;
|
||
|
mixdevs[i].stereo=stmask & mixmask;
|
||
|
mixdevs[i].records=recmask & mixmask;
|
||
|
mixdevs[i].mask=mixmask;
|
||
|
mixdevs[i].name=devnames[i];
|
||
|
mixdevs[i].label=devlabels[i];
|
||
|
mixmask*=2;
|
||
|
}
|
||
|
doStatus();
|
||
|
}
|
||
|
}
|
||
|
~MixCtl(){
|
||
|
if(mixfdopen){
|
||
|
if(mixdevs!=NULL)
|
||
|
free(mixdevs);
|
||
|
close(mixfd);
|
||
|
}
|
||
|
}
|
||
|
bool openOK(){
|
||
|
return mixfdopen;
|
||
|
}
|
||
|
void doStatus(){
|
||
|
ioctl(mixfd, SOUND_MIXER_READ_RECSRC, &recsrc);
|
||
|
for(int i=0;i<nrdevices;i++){
|
||
|
if(mixdevs[i].support)
|
||
|
ioctl(mixfd, MIXER_READ(i), &mixdevs[i].value);
|
||
|
mixdevs[i].recsrc=(recsrc & mixdevs[i].mask);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return volume for a device, optionally reading it from device first.
|
||
|
// Can be used as a way to avoid calling doStatus().
|
||
|
int readVol(int dev, bool read){
|
||
|
if(read)
|
||
|
ioctl(mixfd, MIXER_READ(dev), &mixdevs[dev].value);
|
||
|
return mixdevs[dev].value;
|
||
|
}
|
||
|
|
||
|
// Return left and right componenets of volume for a device.
|
||
|
// If you are lazy, you can call readVol to read from the device, then these
|
||
|
// to get left and right values.
|
||
|
int readLeft(int dev){
|
||
|
return mixdevs[dev].value%256;
|
||
|
}
|
||
|
int readRight(int dev){
|
||
|
return mixdevs[dev].value/256;
|
||
|
}
|
||
|
|
||
|
// Write volume to device. Use setVolume, setLeft and setRight first.
|
||
|
void writeVol(int dev){
|
||
|
ioctl(mixfd, MIXER_WRITE(dev), &mixdevs[dev].value);
|
||
|
}
|
||
|
|
||
|
// Set volume (or left or right component) for a device. You must call writeVol to write it.
|
||
|
void setVol(int dev, int value){
|
||
|
mixdevs[dev].value=value;
|
||
|
}
|
||
|
void setBoth(int dev, int l, int r){
|
||
|
mixdevs[dev].value=256*r+l;
|
||
|
}
|
||
|
void setLeft(int dev, int l){
|
||
|
int r;
|
||
|
if(mixdevs[dev].stereo)
|
||
|
r=mixdevs[dev].value/256;
|
||
|
else
|
||
|
r=l;
|
||
|
mixdevs[dev].value=256*r+l;
|
||
|
}
|
||
|
void setRight(int dev, int r){
|
||
|
int l;
|
||
|
if(mixdevs[dev].stereo)
|
||
|
l=mixdevs[dev].value%256;
|
||
|
else
|
||
|
l=r;
|
||
|
mixdevs[dev].value=256*r+l;
|
||
|
}
|
||
|
|
||
|
// Return record source value for a device, optionally reading it from device first.
|
||
|
bool readRec(int dev, bool read){
|
||
|
if(read){
|
||
|
ioctl(mixfd, SOUND_MIXER_READ_RECSRC, &recsrc);
|
||
|
mixdevs[dev].recsrc=(recsrc & mixdevs[dev].mask);
|
||
|
}
|
||
|
return mixdevs[dev].recsrc;
|
||
|
}
|
||
|
|
||
|
// Write record source values to device. Use setRec first.
|
||
|
void writeRec(){
|
||
|
ioctl(mixfd, SOUND_MIXER_WRITE_RECSRC, &recsrc);
|
||
|
}
|
||
|
|
||
|
// Make a device (not) a record source.
|
||
|
void setRec(int dev, bool rec){
|
||
|
if(rec){
|
||
|
if(caps & SOUND_CAP_EXCL_INPUT)
|
||
|
recsrc=mixdevs[dev].mask;
|
||
|
else
|
||
|
recsrc|=mixdevs[dev].mask;
|
||
|
}
|
||
|
else
|
||
|
recsrc&=~mixdevs[dev].mask;
|
||
|
}
|
||
|
|
||
|
// Return various other info
|
||
|
char *getDevName(){
|
||
|
return device;
|
||
|
}
|
||
|
int getNrDevices(){
|
||
|
return nrdevices;
|
||
|
}
|
||
|
int getCapabilities(){
|
||
|
return caps;
|
||
|
}
|
||
|
bool getSupport(int dev){
|
||
|
return mixdevs[dev].support;
|
||
|
}
|
||
|
bool getStereo(int dev){
|
||
|
return mixdevs[dev].stereo;
|
||
|
}
|
||
|
bool getRecords(int dev){
|
||
|
return mixdevs[dev].records;
|
||
|
}
|
||
|
char *getName(int dev){
|
||
|
return mixdevs[dev].name;
|
||
|
}
|
||
|
char *getLabel(int dev){
|
||
|
return mixdevs[dev].label;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
int mixfd;
|
||
|
int mixfdopen;
|
||
|
char *device;
|
||
|
|
||
|
struct MixDev{
|
||
|
bool support;
|
||
|
bool stereo;
|
||
|
bool recsrc;
|
||
|
bool records;
|
||
|
char *name;
|
||
|
char *label;
|
||
|
int value;
|
||
|
int mask;
|
||
|
};
|
||
|
|
||
|
int nrdevices; // maximum number of devices
|
||
|
int devmask; // supported devices
|
||
|
int stmask; // stereo devices
|
||
|
int recmask; // devices which can be recorded from
|
||
|
int caps; // capabilities
|
||
|
int recsrc; // devices which are being recorded from
|
||
|
struct MixDev *mixdevs;
|
||
|
};
|