1 // mixctl.h - MixCtl class provides control of audio mixer functions 2 // 05/09/98 Release 1.0 Beta1 3 // Copyright (C) 1998 Sam Hawker <shawkie@geocities.com> 4 // This software comes with ABSOLUTELY NO WARRANTY 5 // This software is free software, and you are welcome to redistribute it 6 // under certain conditions 7 // See the COPYING file for details. 8 9 // Although mixctl.h is an integral part of wmmixer, it may also be distributed seperately. 10 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <sys/ioctl.h> 14 #include <sys/types.h> 15 #include <sys/stat.h> 16 #include <fcntl.h> 17 #include <unistd.h> 18 #ifdef __NetBSD__ 19 #include <soundcard.h> 20 #endif 21 #ifdef __FreeBSD__ 22 #include <sys/soundcard.h> 23 #endif 24 #ifdef __linux__ 25 #include <linux/soundcard.h> 26 #endif 27 28 class MixCtl 29 { 30 public: MixCtl(char * dname)31 MixCtl(char *dname){ 32 device=(char *)malloc(sizeof(char)*(strlen(dname)+1)); 33 strcpy(device,dname); 34 if(mixfdopen=(mixfd=open(device,O_RDONLY | O_NONBLOCK))!=-1){ 35 nrdevices=SOUND_MIXER_NRDEVICES; 36 char *devnames[]=SOUND_DEVICE_NAMES; 37 char *devlabels[]=SOUND_DEVICE_LABELS; 38 ioctl(mixfd, SOUND_MIXER_READ_DEVMASK, &devmask); 39 ioctl(mixfd, SOUND_MIXER_READ_STEREODEVS, &stmask); 40 ioctl(mixfd, SOUND_MIXER_READ_RECMASK, &recmask); 41 ioctl(mixfd, SOUND_MIXER_READ_CAPS, &caps); 42 mixdevs=(struct MixDev *)malloc(sizeof(struct MixDev)*nrdevices); 43 int mixmask=1; 44 for(int i=0;i<nrdevices;i++){ 45 mixdevs[i].support=devmask & mixmask; 46 mixdevs[i].stereo=stmask & mixmask; 47 mixdevs[i].records=recmask & mixmask; 48 mixdevs[i].mask=mixmask; 49 mixdevs[i].name=devnames[i]; 50 mixdevs[i].label=devlabels[i]; 51 mixmask*=2; 52 } 53 doStatus(); 54 } 55 } ~MixCtl()56 ~MixCtl(){ 57 if(mixfdopen){ 58 if(mixdevs!=NULL) 59 free(mixdevs); 60 close(mixfd); 61 } 62 } openOK()63 bool openOK(){ 64 return mixfdopen; 65 } doStatus()66 void doStatus(){ 67 ioctl(mixfd, SOUND_MIXER_READ_RECSRC, &recsrc); 68 for(int i=0;i<nrdevices;i++){ 69 if(mixdevs[i].support) 70 ioctl(mixfd, MIXER_READ(i), &mixdevs[i].value); 71 mixdevs[i].recsrc=(recsrc & mixdevs[i].mask); 72 } 73 } 74 75 // Return volume for a device, optionally reading it from device first. 76 // Can be used as a way to avoid calling doStatus(). readVol(int dev,bool read)77 int readVol(int dev, bool read){ 78 if(read) 79 ioctl(mixfd, MIXER_READ(dev), &mixdevs[dev].value); 80 return mixdevs[dev].value; 81 } 82 83 // Return left and right componenets of volume for a device. 84 // If you are lazy, you can call readVol to read from the device, then these 85 // to get left and right values. readLeft(int dev)86 int readLeft(int dev){ 87 return mixdevs[dev].value%256; 88 } readRight(int dev)89 int readRight(int dev){ 90 return mixdevs[dev].value/256; 91 } 92 93 // Write volume to device. Use setVolume, setLeft and setRight first. writeVol(int dev)94 void writeVol(int dev){ 95 ioctl(mixfd, MIXER_WRITE(dev), &mixdevs[dev].value); 96 } 97 98 // Set volume (or left or right component) for a device. You must call writeVol to write it. setVol(int dev,int value)99 void setVol(int dev, int value){ 100 mixdevs[dev].value=value; 101 } setBoth(int dev,int l,int r)102 void setBoth(int dev, int l, int r){ 103 mixdevs[dev].value=256*r+l; 104 } setLeft(int dev,int l)105 void setLeft(int dev, int l){ 106 int r; 107 if(mixdevs[dev].stereo) 108 r=mixdevs[dev].value/256; 109 else 110 r=l; 111 mixdevs[dev].value=256*r+l; 112 } setRight(int dev,int r)113 void setRight(int dev, int r){ 114 int l; 115 if(mixdevs[dev].stereo) 116 l=mixdevs[dev].value%256; 117 else 118 l=r; 119 mixdevs[dev].value=256*r+l; 120 } 121 122 // Return record source value for a device, optionally reading it from device first. readRec(int dev,bool read)123 bool readRec(int dev, bool read){ 124 if(read){ 125 ioctl(mixfd, SOUND_MIXER_READ_RECSRC, &recsrc); 126 mixdevs[dev].recsrc=(recsrc & mixdevs[dev].mask); 127 } 128 return mixdevs[dev].recsrc; 129 } 130 131 // Write record source values to device. Use setRec first. writeRec()132 void writeRec(){ 133 ioctl(mixfd, SOUND_MIXER_WRITE_RECSRC, &recsrc); 134 } 135 136 // Make a device (not) a record source. setRec(int dev,bool rec)137 void setRec(int dev, bool rec){ 138 if(rec){ 139 if(caps & SOUND_CAP_EXCL_INPUT) 140 recsrc=mixdevs[dev].mask; 141 else 142 recsrc|=mixdevs[dev].mask; 143 } 144 else 145 recsrc&=~mixdevs[dev].mask; 146 } 147 148 // Return various other info getDevName()149 char *getDevName(){ 150 return device; 151 } getNrDevices()152 int getNrDevices(){ 153 return nrdevices; 154 } getCapabilities()155 int getCapabilities(){ 156 return caps; 157 } getSupport(int dev)158 bool getSupport(int dev){ 159 return mixdevs[dev].support; 160 } getStereo(int dev)161 bool getStereo(int dev){ 162 return mixdevs[dev].stereo; 163 } getRecords(int dev)164 bool getRecords(int dev){ 165 return mixdevs[dev].records; 166 } getName(int dev)167 char *getName(int dev){ 168 return mixdevs[dev].name; 169 } getLabel(int dev)170 char *getLabel(int dev){ 171 return mixdevs[dev].label; 172 } 173 174 private: 175 int mixfd; 176 int mixfdopen; 177 char *device; 178 179 struct MixDev{ 180 bool support; 181 bool stereo; 182 bool recsrc; 183 bool records; 184 char *name; 185 char *label; 186 int value; 187 int mask; 188 }; 189 190 int nrdevices; // maximum number of devices 191 int devmask; // supported devices 192 int stmask; // stereo devices 193 int recmask; // devices which can be recorded from 194 int caps; // capabilities 195 int recsrc; // devices which are being recorded from 196 struct MixDev *mixdevs; 197 }; 198