Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
	return -1;
183
}