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