1 
2 /*
3  *  Diverse SLab audio routines.
4  *  Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5  *
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 3 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 
23 /*
24  * These are largely device specific operations for the audio devices. Some of
25  * the calls are general, but may eventually be used by several of the SLab
26  * applications.
27  *
28  * The operations for audio control are rather ugly. The application sets up
29  * a number of values in the controlBuffer, and the engine intermittanly looks
30  * to see if these values are initialised. If so, it acts on the values, and
31  * then clears them. The reason we have to use this indirection is that the
32  * front end applications do not own the audio device, this is under control
33  * of the engine.
34  *
35  *	Jul 28th 96 - Only LINUX code is active.
36  */
37 
38 /*
39  * Audio device structure format definitions.
40  */
41 #include "slabrevisions.h"
42 #include "slabaudiodev.h"
43 
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <unistd.h>
48 
49 static char *SLAB_CONVERT_LABELS[32] =	\
50 	{"Master", "Bass", "Treble", "FM", "PCM", "PC Speaker", "Line", "MIC", \
51 	"CD", "Mix  ", "Pcm2 ", "Rec  ", "Input Gain", "OGain", "none", "none", \
52 	"none", "none", "none", "none", "none", "none", (char *) NULL};
53 
54 extern int setAudioOSSparam(duplexDev *, int, int, int, int);
55 extern int checkAudioOSScaps(duplexDev *, int, int);
56 extern char * getOSSName(int);
57 extern int getOSSRecordability();
58 extern int getOSSCapByName();
59 extern int getOSSCapability();
60 
61 #if (BRISTOL_HAS_ALSA == 1)
62 extern int setAudioALSAparam(duplexDev *, int, char *, int, int);
63 extern int checkAudioALSAcaps(duplexDev *, int);
64 extern void closeALSAmixer(duplexDev *);
65 extern int openALSAmixer(duplexDev *);
66 extern char * getAlsaName(duplexDev *, int);
67 extern int validAlsaDev(duplexDev *, int);
68 
69 extern int setAlsaRecordSource();
70 extern int getAlsaRecordability();
71 extern int getAlsaMutability();
72 extern int getAlsaStereoStatus();
73 extern int getAlsaValue();
74 extern int setAlsaValue();
75 extern int setAlsaMute();
76 extern int getAlsaDeviceName();
77 extern int getAlsaCapByName();
78 extern int getAlsaCapability();
79 #endif
80 
81 /*
82  * Setup audio parameters with device support.
83  */
84 void
SL_setAudioDevParam2(audioDev,devID,param,left,right)85 SL_setAudioDevParam2(audioDev, devID, param, left, right)
86 duplexDev *audioDev;
87 int param, devID;
88 short left, right;
89 {
90 	if ((devID < 0) || (devID >= MAX_DEVICES))
91 		return;
92 	if (audioDev->cflags & SLAB_NO_CONTROLS)
93 		return;
94 
95 #if (BRISTOL_HAS_ALSA == 1)
96 	if ((audioDev->flags & AUDIO_ALSA) != 0)
97 	{
98 		/*
99 		 * These were OSS calls. We only want to interpret a few of them.
100 		if (param > 18)
101 			return;
102 		 */
103 		/*
104 		 * We cannot force this on ALSA, since there are likely issues the
105 		 * controller types - use an interpreted name.
106 		 */
107 		setAudioALSAparam(audioDev, devID, SLAB_CONVERT_LABELS[param],
108 			left, right);
109 		return;
110 	}
111 #endif
112 
113 	setAudioOSSparam(audioDev, devID, param, left, right);
114 }
115 
116 void
mixerClose(audioDev)117 mixerClose(audioDev)
118 duplexDev *audioDev;
119 {
120 #if (BRISTOL_HAS_ALSA == 1)
121 	if (audioDev->cflags & SLAB_AUDIODBG)
122 		printf("mixerClose()\n");
123 
124 	if ((audioDev->flags & AUDIO_ALSA) != 0)
125 	{
126 		closeALSAmixer(audioDev);
127 	} else
128 #endif
129 	{
130 		if (audioDev->mixerFD > 0)
131 			close(audioDev->mixerFD);
132 	}
133 	audioDev->mixerFD = -1;
134 }
135 
136 int
mixerOpen(audioDev)137 mixerOpen(audioDev)
138 duplexDev *audioDev;
139 {
140 #if (BRISTOL_HAS_ALSA == 1)
141 	if (audioDev->cflags & SLAB_AUDIODBG)
142 		printf("mixerOpen()\n");
143 
144 	if ((audioDev->flags & AUDIO_ALSA) != 0)
145 	{
146 		audioDev->monoCaps = 0;
147 		audioDev->stereoCaps = 0;
148 		audioDev->recordCaps = 0;
149 		return(openALSAmixer(audioDev));
150 	} else
151 #endif
152 	{
153 		if (audioDev->mixerName[0] != '\0')
154 		{
155 			audioDev->mixerFD = open(audioDev->mixerName, O_RDWR);
156 		}
157 	}
158 	return(audioDev->mixerFD);
159 }
160 
161 char *
getControllerName(audioDev,controller)162 getControllerName(audioDev, controller)
163 duplexDev *audioDev;
164 {
165 #if (BRISTOL_HAS_ALSA == 1)
166 	if ((audioDev->flags & AUDIO_ALSA) != 0)
167 		return((char *) getAlsaName(audioDev, controller));
168 #endif
169 
170 	return (char *) getOSSName(controller);
171 }
172 
173 int
setRecordSource(audioDev,controller,position)174 setRecordSource(audioDev, controller, position)
175 duplexDev *audioDev;
176 {
177 #if (BRISTOL_HAS_ALSA == 1)
178 	if ((audioDev->flags & AUDIO_ALSA) != 0)
179 		return setAlsaRecordSource(audioDev, controller, position);
180 #endif
181 
182 	return -1;
183 }
184 
185 int
getRecordability(audioDev,controller)186 getRecordability(audioDev, controller)
187 duplexDev *audioDev;
188 {
189 #if (BRISTOL_HAS_ALSA == 1)
190 	if ((audioDev->flags & AUDIO_ALSA) != 0)
191 		return getAlsaRecordability(audioDev, controller);
192 #endif
193 
194 	return getOSSRecordability(audioDev, controller);
195 }
196 
197 int
getMutability(audioDev,controller)198 getMutability(audioDev, controller)
199 duplexDev *audioDev;
200 {
201 #if (BRISTOL_HAS_ALSA == 1)
202 	if ((audioDev->flags & AUDIO_ALSA) != 0)
203 		return getAlsaMutability(audioDev, controller);
204 #endif
205 	/*
206 	 * -3 indicates no ALSA support
207 	 */
208 	return -3;
209 }
210 
211 int
getStereoStatus(audioDev,controller)212 getStereoStatus(audioDev, controller)
213 duplexDev *audioDev;
214 {
215 #if (BRISTOL_HAS_ALSA == 1)
216 	if ((audioDev->flags & AUDIO_ALSA) != 0)
217 		return getAlsaStereoStatus(audioDev, controller);
218 #endif
219 	return -1;
220 }
221 
222 int
getValue(audioDev,controller,side)223 getValue(audioDev, controller, side)
224 duplexDev *audioDev;
225 {
226 #if (BRISTOL_HAS_ALSA == 1)
227 	if ((audioDev->flags & AUDIO_ALSA) != 0)
228 		return getAlsaValue(audioDev, controller, side);
229 #endif
230 	return -1;
231 }
232 
233 int
setAudioValue(audioDev,controller,side,value)234 setAudioValue(audioDev, controller, side, value)
235 duplexDev *audioDev;
236 {
237 	if (audioDev->cflags & SLAB_AUDIODBG)
238 		printf("setAudioValue(%p, %i, %i, %i)\n", audioDev, controller, side, value);
239 	if (audioDev->cflags & SLAB_NO_CONTROLS)
240 	{
241 		return 0;
242 	}
243 
244 #if (BRISTOL_HAS_ALSA == 1)
245 	if ((audioDev->flags & AUDIO_ALSA) != 0)
246 		return setAlsaValue(audioDev, controller, side, value);
247 #endif
248 	return -1;
249 }
250 
251 int
setAudioMute(audioDev,controller,value)252 setAudioMute(audioDev, controller, value)
253 duplexDev *audioDev;
254 {
255 	if (audioDev->cflags & SLAB_AUDIODBG)
256 		printf("setAudioMute()\n");
257 
258 #if (BRISTOL_HAS_ALSA == 1)
259 	if ((audioDev->flags & AUDIO_ALSA) != 0)
260 		return setAlsaMute(audioDev, controller, value);
261 #endif
262 	return -1;
263 }
264 
265 int
getAudioCapByName(audioDev,name)266 getAudioCapByName(audioDev, name)
267 duplexDev *audioDev;
268 char *name;
269 {
270 	if (audioDev->cflags & SLAB_AUDIODBG)
271 		printf("getAudioCapByName(%s, %s)\n", audioDev->devName, name);
272 
273 #if (BRISTOL_HAS_ALSA == 1)
274 	if ((audioDev->flags & AUDIO_ALSA) != 0)
275 		return getAlsaCapByName(audioDev, name);
276 #endif
277 	return getOSSCapByName(audioDev, name);
278 }
279 
280 int
getAudioCapability(audioDev,controller)281 getAudioCapability(audioDev, controller)
282 duplexDev *audioDev;
283 {
284 	if (audioDev->cflags & SLAB_AUDIODBG)
285 		printf("getAudioCapability(%s, %i)\n", audioDev->devName, controller);
286 
287 #if (BRISTOL_HAS_ALSA == 1)
288 	if ((audioDev->flags & AUDIO_ALSA) != 0)
289 	{
290 		return getAlsaCapability(audioDev, controller);
291 	}
292 #endif
293 	return getOSSCapability(audioDev, controller);
294 }
295 
296 int
validDev(audioDev,index)297 validDev(audioDev, index)
298 duplexDev *audioDev;
299 {
300 #if (BRISTOL_HAS_ALSA == 1)
301 	if ((audioDev->flags & AUDIO_ALSA) != 0)
302 		return validAlsaDev(audioDev, index);
303 #endif
304 	return(0);
305 }
306 
307