1*499069deSDavid du Colombier /* 2*499069deSDavid du Colombier * Linux and BSD 3*499069deSDavid du Colombier */ 4*499069deSDavid du Colombier #include <sys/ioctl.h> 5*499069deSDavid du Colombier #ifdef __linux__ 6*499069deSDavid du Colombier #include <linux/soundcard.h> 7*499069deSDavid du Colombier #else 8*499069deSDavid du Colombier #include <sys/soundcard.h> 9*499069deSDavid du Colombier #endif 10*499069deSDavid du Colombier #include "u.h" 11*499069deSDavid du Colombier #include "lib.h" 12*499069deSDavid du Colombier #include "dat.h" 13*499069deSDavid du Colombier #include "fns.h" 14*499069deSDavid du Colombier #include "error.h" 15*499069deSDavid du Colombier #include "devaudio.h" 16*499069deSDavid du Colombier 17*499069deSDavid du Colombier enum 18*499069deSDavid du Colombier { 19*499069deSDavid du Colombier Channels = 2, 20*499069deSDavid du Colombier Rate = 44100, 21*499069deSDavid du Colombier Bits = 16, 22*499069deSDavid du Colombier Bigendian = 1, 23*499069deSDavid du Colombier }; 24*499069deSDavid du Colombier 25*499069deSDavid du Colombier static int afd = -1; 26*499069deSDavid du Colombier static int cfd= -1; 27*499069deSDavid du Colombier static int speed; 28*499069deSDavid du Colombier 29*499069deSDavid du Colombier /* maybe this should return -1 instead of sysfatal */ 30*499069deSDavid du Colombier void 31*499069deSDavid du Colombier audiodevopen(void) 32*499069deSDavid du Colombier { 33*499069deSDavid du Colombier int t; 34*499069deSDavid du Colombier ulong ul; 35*499069deSDavid du Colombier 36*499069deSDavid du Colombier afd = -1; 37*499069deSDavid du Colombier cfd = -1; 38*499069deSDavid du Colombier if((afd = open("/dev/dsp", OWRITE)) < 0) 39*499069deSDavid du Colombier goto err; 40*499069deSDavid du Colombier if((cfd = open("/dev/mixer", ORDWR)) < 0) 41*499069deSDavid du Colombier goto err; 42*499069deSDavid du Colombier 43*499069deSDavid du Colombier t = Bits; 44*499069deSDavid du Colombier if(ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &t) < 0) 45*499069deSDavid du Colombier goto err; 46*499069deSDavid du Colombier 47*499069deSDavid du Colombier t = Channels-1; 48*499069deSDavid du Colombier if(ioctl(afd, SNDCTL_DSP_STEREO, &t) < 0) 49*499069deSDavid du Colombier goto err; 50*499069deSDavid du Colombier 51*499069deSDavid du Colombier speed = Rate; 52*499069deSDavid du Colombier ul = Rate; 53*499069deSDavid du Colombier if(ioctl(afd, SNDCTL_DSP_SPEED, &ul) < 0) 54*499069deSDavid du Colombier goto err; 55*499069deSDavid du Colombier 56*499069deSDavid du Colombier return; 57*499069deSDavid du Colombier 58*499069deSDavid du Colombier err: 59*499069deSDavid du Colombier if(afd >= 0) 60*499069deSDavid du Colombier close(afd); 61*499069deSDavid du Colombier afd = -1; 62*499069deSDavid du Colombier oserror(); 63*499069deSDavid du Colombier } 64*499069deSDavid du Colombier 65*499069deSDavid du Colombier void 66*499069deSDavid du Colombier audiodevclose(void) 67*499069deSDavid du Colombier { 68*499069deSDavid du Colombier close(afd); 69*499069deSDavid du Colombier close(cfd); 70*499069deSDavid du Colombier afd = -1; 71*499069deSDavid du Colombier cfd = -1; 72*499069deSDavid du Colombier } 73*499069deSDavid du Colombier 74*499069deSDavid du Colombier static struct { 75*499069deSDavid du Colombier int id9; 76*499069deSDavid du Colombier int id; 77*499069deSDavid du Colombier } names[] = { 78*499069deSDavid du Colombier Vaudio, SOUND_MIXER_VOLUME, 79*499069deSDavid du Colombier Vbass, SOUND_MIXER_BASS, 80*499069deSDavid du Colombier Vtreb, SOUND_MIXER_TREBLE, 81*499069deSDavid du Colombier Vline, SOUND_MIXER_LINE, 82*499069deSDavid du Colombier Vpcm, SOUND_MIXER_PCM, 83*499069deSDavid du Colombier Vsynth, SOUND_MIXER_SYNTH, 84*499069deSDavid du Colombier Vcd, SOUND_MIXER_CD, 85*499069deSDavid du Colombier Vmic, SOUND_MIXER_MIC, 86*499069deSDavid du Colombier // "record", SOUND_MIXER_RECLEV, 87*499069deSDavid du Colombier // "mix", SOUND_MIXER_IMIX, 88*499069deSDavid du Colombier // "pcm2", SOUND_MIXER_ALTPCM, 89*499069deSDavid du Colombier Vspeaker, SOUND_MIXER_SPEAKER 90*499069deSDavid du Colombier // "line1", SOUND_MIXER_LINE1, 91*499069deSDavid du Colombier // "line2", SOUND_MIXER_LINE2, 92*499069deSDavid du Colombier // "line3", SOUND_MIXER_LINE3, 93*499069deSDavid du Colombier // "digital1", SOUND_MIXER_DIGITAL1, 94*499069deSDavid du Colombier // "digital2", SOUND_MIXER_DIGITAL2, 95*499069deSDavid du Colombier // "digital3", SOUND_MIXER_DIGITAL3, 96*499069deSDavid du Colombier // "phonein", SOUND_MIXER_PHONEIN, 97*499069deSDavid du Colombier // "phoneout", SOUND_MIXER_PHONEOUT, 98*499069deSDavid du Colombier // "radio", SOUND_MIXER_RADIO, 99*499069deSDavid du Colombier // "video", SOUND_MIXER_VIDEO, 100*499069deSDavid du Colombier // "monitor", SOUND_MIXER_MONITOR, 101*499069deSDavid du Colombier // "igain", SOUND_MIXER_IGAIN, 102*499069deSDavid du Colombier // "ogain", SOUND_MIXER_OGAIN, 103*499069deSDavid du Colombier }; 104*499069deSDavid du Colombier 105*499069deSDavid du Colombier static int 106*499069deSDavid du Colombier lookname(int id9) 107*499069deSDavid du Colombier { 108*499069deSDavid du Colombier int i; 109*499069deSDavid du Colombier 110*499069deSDavid du Colombier for(i=0; i<nelem(names); i++) 111*499069deSDavid du Colombier if(names[i].id9 == id9) 112*499069deSDavid du Colombier return names[i].id; 113*499069deSDavid du Colombier return -1; 114*499069deSDavid du Colombier } 115*499069deSDavid du Colombier 116*499069deSDavid du Colombier void 117*499069deSDavid du Colombier audiodevsetvol(int what, int left, int right) 118*499069deSDavid du Colombier { 119*499069deSDavid du Colombier int id; 120*499069deSDavid du Colombier ulong x; 121*499069deSDavid du Colombier int can, v; 122*499069deSDavid du Colombier 123*499069deSDavid du Colombier if(cfd < 0) 124*499069deSDavid du Colombier error("audio device not open"); 125*499069deSDavid du Colombier if(what == Vspeed){ 126*499069deSDavid du Colombier x = left; 127*499069deSDavid du Colombier if(ioctl(afd, SNDCTL_DSP_SPEED, &x) < 0) 128*499069deSDavid du Colombier oserror(); 129*499069deSDavid du Colombier speed = x; 130*499069deSDavid du Colombier return; 131*499069deSDavid du Colombier } 132*499069deSDavid du Colombier if((id = lookname(what)) < 0) 133*499069deSDavid du Colombier return; 134*499069deSDavid du Colombier if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0) 135*499069deSDavid du Colombier can = ~0; 136*499069deSDavid du Colombier if(!(can & (1<<id))) 137*499069deSDavid du Colombier return; 138*499069deSDavid du Colombier v = left | (right<<8); 139*499069deSDavid du Colombier if(ioctl(cfd, MIXER_WRITE(id), &v) < 0) 140*499069deSDavid du Colombier oserror(); 141*499069deSDavid du Colombier } 142*499069deSDavid du Colombier 143*499069deSDavid du Colombier void 144*499069deSDavid du Colombier audiodevgetvol(int what, int *left, int *right) 145*499069deSDavid du Colombier { 146*499069deSDavid du Colombier int id; 147*499069deSDavid du Colombier int can, v; 148*499069deSDavid du Colombier 149*499069deSDavid du Colombier if(cfd < 0) 150*499069deSDavid du Colombier error("audio device not open"); 151*499069deSDavid du Colombier if(what == Vspeed){ 152*499069deSDavid du Colombier *left = *right = speed; 153*499069deSDavid du Colombier return; 154*499069deSDavid du Colombier } 155*499069deSDavid du Colombier if((id = lookname(what)) < 0) 156*499069deSDavid du Colombier return; 157*499069deSDavid du Colombier if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0) 158*499069deSDavid du Colombier can = ~0; 159*499069deSDavid du Colombier if(!(can & (1<<id))) 160*499069deSDavid du Colombier return; 161*499069deSDavid du Colombier if(ioctl(cfd, MIXER_READ(id), &v) < 0) 162*499069deSDavid du Colombier oserror(); 163*499069deSDavid du Colombier *left = v&0xFF; 164*499069deSDavid du Colombier *right = (v>>8)&0xFF; 165*499069deSDavid du Colombier } 166*499069deSDavid du Colombier 167*499069deSDavid du Colombier int 168*499069deSDavid du Colombier audiodevwrite(void *v, int n) 169*499069deSDavid du Colombier { 170*499069deSDavid du Colombier int m, tot; 171*499069deSDavid du Colombier 172*499069deSDavid du Colombier for(tot=0; tot<n; tot+=m) 173*499069deSDavid du Colombier if((m = write(afd, (uchar*)v+tot, n-tot)) <= 0) 174*499069deSDavid du Colombier oserror(); 175*499069deSDavid du Colombier return tot; 176*499069deSDavid du Colombier } 177*499069deSDavid du Colombier 178*499069deSDavid du Colombier int 179*499069deSDavid du Colombier audiodevread(void *v, int n) 180*499069deSDavid du Colombier { 181*499069deSDavid du Colombier error("no reading"); 182*499069deSDavid du Colombier } 183