4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1989-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This file contains routines to read and write the audio device state.
35 #include <sys/types.h>
38 #include <sys/ioctl.h>
40 #include <libaudio_impl.h>
41 #include <audio_errno.h>
42 #include <audio_hdr.h>
43 #include <audio_device.h>
47 * Get device information structure.
50 audio_getinfo(int fd
, Audio_info
*ip
)
52 if (ioctl(fd
, AUDIO_GETINFO
, (char *)ip
) < 0) {
53 return (AUDIO_UNIXERROR
);
55 return (AUDIO_SUCCESS
);
60 * Set device information structure.
61 * The calling routine should use AUDIO_INITINFO prior to setting new values.
64 audio_setinfo(int fd
, Audio_info
*ip
)
66 if (ioctl(fd
, AUDIO_SETINFO
, (char *)ip
) < 0) {
67 return (AUDIO_UNIXERROR
);
69 return (AUDIO_SUCCESS
);
74 * Return an Audio_hdr corresponding to the encoding configuration
75 * of the audio device on 'fd'.
78 audio__setplayhdr(int fd
, Audio_hdr
*hdrp
, unsigned int which
)
82 struct audio_prinfo
*prinfo
;
85 if (which
& AUDIO__PLAY
)
87 else if (which
& AUDIO__RECORD
)
88 prinfo
= &info
.record
;
90 return (AUDIO_ERR_BADARG
);
92 if (which
& AUDIO__SET
) {
93 thdr
= *hdrp
; /* save original hdr */
94 AUDIO_INITINFO(&info
);
95 prinfo
->sample_rate
= hdrp
->sample_rate
;
96 prinfo
->channels
= hdrp
->channels
;
97 prinfo
->encoding
= hdrp
->encoding
;
98 prinfo
->precision
= hdrp
->bytes_per_unit
* 8;
99 err
= audio_setinfo(fd
, &info
);
101 err
= audio_getinfo(fd
, &info
);
104 /* Decode back into the header structure */
105 /* since the I_SMSG is set, upon completion of updating */
106 /* the format, the driver sends the msg so the */
107 /* system call is interrupted. For now, just ignore this */
108 if ((err
== AUDIO_SUCCESS
) || (errno
== EINTR
)) {
109 hdrp
->sample_rate
= prinfo
->sample_rate
;
110 hdrp
->channels
= prinfo
->channels
;
111 hdrp
->data_size
= AUDIO_UNKNOWN_SIZE
;
112 hdrp
->encoding
= prinfo
->encoding
;
113 switch (hdrp
->encoding
) {
114 case AUDIO_ENCODING_ULAW
:
115 case AUDIO_ENCODING_ALAW
:
116 case AUDIO_ENCODING_LINEAR
:
117 case AUDIO_ENCODING_LINEAR8
:
118 case AUDIO_ENCODING_FLOAT
:
119 hdrp
->bytes_per_unit
= prinfo
->precision
/ 8;
120 hdrp
->samples_per_unit
= 1;
123 return (AUDIO_ERR_ENCODING
);
125 if (which
& AUDIO__SET
) {
126 /* Check to see if *all* changes took effect */
127 if (audio_cmp_hdr(hdrp
, &thdr
) != 0)
128 return (AUDIO_ERR_NOEFFECT
);
136 * Attempt to configure the audio device to match a particular encoding.
140 * Set and/or set individual state values.
141 * This routine is generally invoked by using the audio_set_*()
142 * and audio_get_*() macros.
143 * The 'valp' argument is always a pointer to an unsigned int.
144 * Conversions to/from (unsigned char) flags are taken care of.
147 audio__setval(int fd
, unsigned int *valp
, unsigned int which
)
150 struct audio_prinfo
*prinfo
;
155 /* Set a pointer to the value of interest */
156 if (which
& AUDIO__PLAY
)
158 else if (which
& AUDIO__RECORD
)
159 prinfo
= &info
.record
;
160 else if ((which
& AUDIO__SETVAL_MASK
) != AUDIO__MONGAIN
)
161 return (AUDIO_ERR_BADARG
);
164 switch (which
& AUDIO__SETVAL_MASK
) {
166 up
= &prinfo
->port
; break;
168 up
= &prinfo
->samples
; break;
170 cp
= &prinfo
->error
; break;
172 up
= &prinfo
->eof
; break;
174 cp
= &prinfo
->open
; break;
176 cp
= &prinfo
->active
; break;
178 cp
= &prinfo
->waiting
; break;
180 up
= &prinfo
->gain
; break;
182 up
= &info
.monitor_gain
; break;
184 cp
= &prinfo
->balance
; break;
186 return (AUDIO_ERR_BADARG
);
189 if (which
& AUDIO__SET
) {
190 /* Init so that only the value of interest is changed */
191 AUDIO_INITINFO(&info
);
195 *cp
= (unsigned char) *valp
;
197 err
= audio_setinfo(fd
, &info
);
199 err
= audio_getinfo(fd
, &info
);
201 if (err
== AUDIO_SUCCESS
) {
205 *valp
= (unsigned)*cp
;
211 * Get/set gain value.
212 * NOTE: legal values are floating-point double 0. - 1.
215 audio__setgain(int fd
, double *valp
, unsigned int which
)
220 if (which
& AUDIO__SET
) {
221 if ((*valp
< 0.) || (*valp
> 1.))
222 return (AUDIO_ERR_BADARG
);
224 /* Map value into legal range */
225 x
= ((unsigned)(*valp
* (AUDIO_MAX_GAIN
- AUDIO_MIN_GAIN
))) +
229 /* Get or set the new value */
230 err
= audio__setval(fd
, &x
, which
);
231 if (err
== AUDIO_SUCCESS
) {
232 /* Map value back to double */
233 *valp
= ((double)(x
- AUDIO_MIN_GAIN
) /
234 (AUDIO_MAX_GAIN
- AUDIO_MIN_GAIN
));
240 * Set Pause/resume flags.
241 * Can set play and record individually or together.
244 audio__setpause(int fd
, unsigned int which
)
250 AUDIO_INITINFO(&info
);
252 if ((which
& AUDIO__SETVAL_MASK
) == AUDIO__PAUSE
) {
254 } else if ((which
& AUDIO__SETVAL_MASK
) == AUDIO__RESUME
) {
257 return (AUDIO_ERR_BADARG
);
260 if (which
& AUDIO__PLAY
) {
263 if (which
& AUDIO__RECORD
) {
264 info
.record
.pause
= x
;
267 /* Set the new value */
268 err
= audio_setinfo(fd
, &info
);
270 /* Check to see if this took effect */
271 if (err
== AUDIO_SUCCESS
) {
272 if (((which
& AUDIO__PLAY
) && (info
.play
.pause
!= x
)) ||
273 ((which
& AUDIO__RECORD
) && (info
.record
.pause
!= x
)))
274 return (AUDIO_ERR_NOEFFECT
);
281 * Flush play and/or record buffers.
284 audio__flush(int fd
, unsigned int which
)
288 flag
= (which
& AUDIO__PLAY
) ? FLUSHW
: 0;
289 flag
|= (which
& AUDIO__RECORD
) ? FLUSHR
: 0;
291 return ((ioctl(fd
, I_FLUSH
, flag
) < 0) ?
292 AUDIO_UNIXERROR
: AUDIO_SUCCESS
);
297 * Wait synchronously for output buffers to finish playing.
298 * If 'sig' is TRUE, signals may interrupt the drain.
301 audio_drain(int fd
, int sig
)
303 while (ioctl(fd
, AUDIO_DRAIN
, 0) < 0) {
304 if (errno
!= EINTR
) {
305 return (AUDIO_UNIXERROR
);
309 return (AUDIO_ERR_INTERRUPTED
);
312 return (AUDIO_SUCCESS
);
316 * Write an EOF marker to the output audio stream.
319 audio_play_eof(int fd
)
321 return (write(fd
, NULL
, 0) < 0 ?
322 AUDIO_UNIXERROR
: AUDIO_SUCCESS
);