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