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/ioctl.h>
45 #include <string.h>
46 
47 #ifdef DEBUG
48 #include <stdio.h>
49 #endif
50 #include <unistd.h>
51 #include <fcntl.h>
52 #include <stdlib.h>
53 #ifndef __FreeBSD__
54 #include <malloc.h>
55 #endif
56 
57 static int setAudioOSS(int, duplexDev *, int, int, int);
58 
59 #if (BRISTOL_HAS_OSS == 1)
60 /*
61  * This may want to be /usr/lib/oss/include/sys/soundcard.h if someone has
62  * purchased the 4Front drivers?
63  */
64 #include <sys/soundcard.h>
65 audio_buf_info bufferInfo;
66 mixer_info mInfo;
67 
68 static char *SLAB_SND_LABELS[SLAB_NRDEVICES] =	SOUND_DEVICE_LABELS;
69 #endif
70 
71 /*
72  * Setup audio parameters with device support.
73  */
74 void
setAudioOSSparam(audioDev,devID,param,left,right)75 setAudioOSSparam(audioDev, devID, param, left, right)
76 duplexDev *audioDev;
77 int param, devID;
78 short left, right;
79 {
80 	if (audioDev->mixerFD > 0)
81 		setAudioOSS(audioDev->mixerFD, audioDev, param, left, right);
82 }
83 
84 /*
85  * Binned since alsa support was implemented.
86  *
87  * This is a device specific routine. We take the fd, parameter, and left
88  * right values, and configure the device. These routines should be used by the
89  * engine to do the actual audio horsework.
90  *
91  * This is actually an internal routine, it should not be called from outside
92  * of this file.
93  */
94 static int
setAudioOSS(fd,audioDev,param,valueL,valueR)95 setAudioOSS(fd, audioDev, param, valueL, valueR)
96 duplexDev *audioDev;
97 {
98 #if (BRISTOL_HAS_OSS == 1)
99 	int value, command;
100 
101 	switch(param) {
102 		case SLAB_REC_SRC:
103 		case SLAB_MM_CD:
104 		case SLAB_MM_MIC:
105 		case SLAB_MM_LINE:
106 		case SLAB_MM_LINE1:
107 		case SLAB_MM_LINE2:
108 		case SLAB_MM_LINE3:
109 		case SLAB_MM_SYNTH:
110 		case SLAB_MM_PCM:
111 		case SLAB_TREBLE:
112 		case SLAB_BASS:
113 		case SLAB_MID:
114 		case SLAB_INPUT_GAIN:
115 		case SLAB_VOL_CD:
116 		case SLAB_VOL_MIC:
117 		case SLAB_VOL_LINE:
118 		case SLAB_VOL_LINE1:
119 		case SLAB_VOL_LINE2:
120 		case SLAB_VOL_LINE3:
121 		case SLAB_VOL_SYNTH:
122 		case SLAB_VOL_PCM:
123 		default:
124 		/*
125 		 * These are all the rest, which should be from the microMixer,
126 		 * scaled to 100 already.
127 		 */
128 			command = param & SLAB_MM_MASK;
129 			value = (valueR << 8) +
130 				valueL;
131 	}
132 #endif /* linux */
133 
134 #ifdef DEBUG
135 	printf("Command: %x, value: %x\n", command, value);
136 #endif
137 
138 #if (BRISTOL_HAS_OSS == 1)
139 #ifdef IOCTL_DBG
140 	if (audioDev->cflags & SLAB_AUDIODBG)
141 		printf("ioctl(%i, MIXER_WRITE(%i), %i)\n", fd, command, value);
142 #endif
143 	if (ioctl(fd, MIXER_WRITE(command), &value) == -1) {
144 /*
145 			printf("Error setting audio parameter %s\n",
146 				SLAB_SND_LABELS[command]);
147 */
148 		return(0);
149 	}
150 #endif
151 
152 	return(0);
153 }
154 
155 void
checkAudioOSScaps(audioDev,devID,fd)156 checkAudioOSScaps(audioDev, devID, fd)
157 duplexDev *audioDev;
158 int devID, fd;
159 {
160 #if (BRISTOL_HAS_OSS == 1)
161 	int stereodevs = 0;
162 
163 #ifdef DEBUG
164 	printf("checkAudioCaps2(%i, %i)\n", devID, fd);
165 #endif
166 
167     if (ioctl(fd, SOUND_MIXER_READ_STEREODEVS, &stereodevs) == -1)
168 	{
169 #ifdef IOCTL_DBG
170 		if (audioDev->cflags & SLAB_AUDIODBG)
171 #endif
172 			printf("Failed to get stereo capabilities: %08x\n", stereodevs);
173 	} else {
174 #ifdef IOCTL_DBG
175 		if (audioDev->cflags & SLAB_AUDIODBG)
176 			printf("Capabilities: %08x\n", stereodevs);
177 #endif
178 		audioDev->stereoCaps = stereodevs;
179 	}
180 
181 
182 #ifdef DEBUG
183 	for (i = 1; i < 131072; i = i << 1) {
184 		if (i & stereodevs)
185 			printf("Found stereo dev %08x\n", i);
186 	}
187 #endif
188 
189 	stereodevs = 0;
190     if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &stereodevs) == -1)
191 	{
192 #ifdef IOCTL_DBG
193 		if (audioDev->cflags & SLAB_AUDIODBG)
194 #endif
195 			printf("Failed to get audio capabilities: %08x\n", stereodevs);
196 	} else {
197 #ifdef IOCTL_DBG
198 		if (audioDev->cflags & SLAB_AUDIODBG)
199 			printf("Mono Capabilities: %08x\n", stereodevs);
200 #endif
201 		audioDev->monoCaps = stereodevs;
202 	}
203 
204 
205 	stereodevs = 0;
206     if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &stereodevs) == -1)
207 	{
208 #ifdef IOCTL_DBG
209 		if (audioDev->cflags & SLAB_AUDIODBG)
210 #endif
211 			printf("Failed to get record capabilities: %08x\n", stereodevs);
212 	} else {
213 #ifdef IOCTL_DBG
214 		if (audioDev->cflags & SLAB_AUDIODBG)
215 			printf("Record Caps: %08x\n", stereodevs);
216 #endif
217 		audioDev->recordCaps = stereodevs;
218 	}
219 
220 #ifdef DEBUG
221 	for (i = 1; i < 131072; i = i << 1) {
222 		if (i & stereodevs)
223 			printf("Found mono dev %08x\n", i);
224 	}
225 #endif /* DEBUG */
226 #endif /* linux */
227 }
228 
229 char *
getOSSName(controller)230 getOSSName(controller)
231 int controller;
232 {
233 	char *name = NULL;
234 
235 #if (BRISTOL_HAS_OSS == 1)
236 	if ((controller < 0) || (controller > SOUND_MIXER_NRDEVICES))
237 		return("none");
238 
239 	name = SLAB_SND_LABELS[controller];
240 #endif
241 	return(name);
242 }
243 
244 int
getOSSCapByName(audioDev,name)245 getOSSCapByName(audioDev, name)
246 duplexDev *audioDev;
247 char *name;
248 {
249 #if (BRISTOL_HAS_OSS == 1)
250 	int i;
251 
252 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
253 	{
254 		if (strcmp(SLAB_SND_LABELS[i], name) == 0)
255 			return i;
256 	}
257 #endif
258 	return(-1);
259 }
260 
261 int
getOSSCapability(audioDev,controller)262 getOSSCapability(audioDev, controller)
263 duplexDev *audioDev;
264 {
265 	if ((audioDev->stereoCaps | audioDev->monoCaps) & (1 << controller))
266 		return controller;
267 	return(-1);
268 }
269 
270 int
getOSSRecordability(audioDev,cont)271 getOSSRecordability(audioDev, cont)
272 duplexDev *audioDev;
273 {
274 	if (audioDev->cflags & SLAB_AUDIODBG)
275 		printf("getOSSRecordability(%i, %i)\n", audioDev->devID, cont);
276 
277 	if (audioDev->recordCaps & (1<<cont))
278 		return(1);
279 	/*
280 	 * -2 indicates no support
281 	 */
282 	return(-2);
283 }
284 
285