AudioDevice.cc revision 4ab75253616c6d68e967c10221bb663c0bfa99df
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <errno.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
#include <stropts.h>
#include <AudioDebug.h>
#include <AudioDevice.h>
#define irint(d) ((int)(d))
// class AudioDevice methods
// class AudioInfo Constructor
{
Clear();
}
// Reset the info structure
void AudioInfo::
Clear()
{
}
// Initialize default device access mode, used when no mode is supplied
// Default audio device and environment variable names
// Constructor with optional path and mode arguments
const char *path, // filename
{
}
// Destructor must call the local Close() routine
~AudioDevice()
{
// If the device was open, close it
if (opened()) {
(void) Close();
}
}
// Return TRUE if stream is open
opened() const
{
return (isfdset());
}
// Get the audio device type
GetDeviceType() const
{
return (devtype);
}
// Get the device information structure
{
// Get the device information
return (AUDIO_SUCCESS);
}
// Set the device information structure (and return it updated)
{
int i;
if (!opened())
// Set the device information
// Try a couple of times if interrupted by a signal
for (i = 0; i < 3; i++) {
// Save the new encoding
if (!err)
return (err);
}
break;
}
return (AUDIO_UNIXERROR);
}
// The normal device receives signals only on i/o conditions
// For state change notification, open the control device
{
int flag;
// Flag of zero disables SIGPOLL
flag = 0;
if (on) {
// Enable signals for the accessed streams
}
// Set the streams flag
return (RaiseError(AUDIO_UNIXERROR));
return (AUDIO_SUCCESS);
}
// Clear the cached read header
void AudioDevice::
clearhdr()
{
}
// Decode a device info structure into an audio file header
AudioHdr& h) const // header to fill in
{
case AUDIO_ENCODING_ULAW:
break;
case AUDIO_ENCODING_ALAW:
break;
case AUDIO_ENCODING_LINEAR:
break;
default:
return (RaiseError(AUDIO_ERR_ENCODING));
}
if (err == AUDIO_SUCCESS)
h = hdr_local;
return (err);
}
// Decode an audio file header into a device info structure
const AudioHdr& h, // header to decode
{
// Validate header before converting
if (err != AUDIO_SUCCESS)
return (err);
switch (h.encoding) {
case ULAW:
break;
case ALAW:
break;
case LINEAR:
break;
default:
return (RaiseError(AUDIO_ERR_ENCODING));
}
return (AUDIO_SUCCESS);
}
// Figure out what kind of audio device is connected
// XXX - this should be replaced by a capabilities database lookup
void AudioDevice::
{
#ifdef MAX_AUDIO_DEV_LEN
struct audio_device adev;
#else /* 4.1.3 */
int adev;
#endif /* 4.1.3 */
/*
* Spectrum 16, MultiSound and SB16 are all place holders for
* x86 devices.
*/
#ifdef MAX_AUDIO_DEV_LEN
else
#else /* 4.1.3 */
switch (adev) {
case AUDIO_DEV_AMD:
break;
default:
break;
}
#endif /* 4.1.3 */
} else {
// AUDIO_GETDEV not supported. Assume AMD.
}
}
// Return TRUE if the sample rates are within a close tolerance (1%)
unsigned int rate1,
unsigned int rate2)
{
return (FALSE);
return (TRUE);
}
// Return TRUE if the device supports the audio format
// If the sample rate does not match, but is within tolerance, rewrite it.
// XXX - this should *really* be replaced by a capabilities database lookup
AudioHdr& h)
{
return (FALSE);
switch (devtype) {
default: // if unknown type, assume AMD
case AudioDeviceAMD:
return (FALSE);
return (FALSE);
h.sample_rate = 8000;
break;
case AudioDeviceCODEC:
if (h.channels > 2)
return (FALSE);
switch (h.encoding) {
case ULAW:
case ALAW:
case LINEAR:
break;
default:
return (FALSE);
}
h.sample_rate = 5510;
h.sample_rate = 6620;
h.sample_rate = 8000;
h.sample_rate = 9600;
h.sample_rate = 11025;
h.sample_rate = 16000;
h.sample_rate = 18900;
h.sample_rate = 22050;
h.sample_rate = 27420;
h.sample_rate = 32000;
h.sample_rate = 33075;
h.sample_rate = 37800;
h.sample_rate = 44100;
h.sample_rate = 48000;
} else {
return (FALSE);
}
break;
case AudioDeviceSBPRO:
return (FALSE);
if (h.channels > 2)
return (FALSE);
return (FALSE);
break;
case AudioDeviceSB16:
/*
* Place holders for x86 devices, these are treated as if they
* are equivelant to the SB16 for now.
*/
case AudioDeviceSPECTRUM:
case AudioDeviceMULTISOUND:
if (h.channels > 2)
return (FALSE);
switch (h.encoding) {
/*
* The SBPro driver does not do ALAW
*/
case ULAW:
break;
case LINEAR:
// We don't support 8bit linear as this should
// be unsigned linear and we have assumed signed all
// along. Must change this in XAL
return (FALSE);
break;
default:
return (FALSE);
}
// I don't know if this is correct - sdy check it out please
return (FALSE);
break;
}
return (TRUE);
}
// Set input encoding
AudioHdr& h) // header (updated)
{
// Convert header to encoding fields
if (err == AUDIO_SUCCESS) {
// Set the device encoding
if (!err)
h = readhdr;
}
return (err);
}
// Set output encoding
AudioHdr& h) // header (updated)
{
// Convert header to encoding fields
if (err == AUDIO_SUCCESS) {
// Set the device encoding
if (err == AUDIO_SUCCESS) {
// Save (and return) the new encoding
if (!err)
(void) AudioStream::updateheader(h);
}
}
return (err);
}
// Get input encoding
{
AudioHdr h;
// If the cached header is valid, use it.
// XXX - If a state change determines the encoding changed, we had
// XXX - better invalidate the cache and call this routine again.
return (readhdr);
// Get the device state
readhdr = h;
}
return (h);
}
// Get output encoding
{
AudioHdr h;
// Get the device state
(void) AudioStream::updateheader(h);
}
return (h);
}
// SetHeader function sets the output encoding
const AudioHdr& h) // header
{
// Set the output header in the cached structure
return (err);
}
// If the device is open, set the output header
}
// GetHeader returns the cached input encoding
{
if (GetPlayOpen()) {
return (GetWriteHeader());
} else {
return (GetReadHeader());
}
}
// Open an audio device for output
// Open the device and set the output encoding
Create()
{
if (!hdrset())
return (RaiseError(AUDIO_ERR_BADHDR));
if (err == AUDIO_SUCCESS)
return (err);
}
// Open an audio device
Open()
{
// If name was NULL, use default search path
return (OpenPath());
}
// Open an audio device, with a path environment as a fall-back
const char *path)
{
char *str;
char *wrk;
char *component;
int openmode;
// Convert the open mode to an int argument for open()
// Can't open if already opened or if mode not set
// If non-blocking set, this counts for open(), too
if (!GetBlocking())
openmode |= O_NONBLOCK;
// Search path:
// 1) try name, if supplied: fail if no good
// 2) if no name, try to find 'path' in the environment:
// if not found, assume 'path' is the path string itself
// first try the path as a deivce name
// then, try every colon-separated path component in it
// Try path as environment variable name, else assume it is a path
// Make a copy of the path, in case we have to parse it
// Try the whole string, then every component
switch (err) {
case AUDIO_SUCCESS: // found a device
case AUDIO_ERR_DEVICEBUSY:
delete wrk;
return (RaiseError(err));
}
break;
*str++ = '\0';
}
delete wrk;
}
}
// Attempt to open the audio device with the given name and mode
const char *devname,
int openmode)
{
int desc;
// If the name is changing, set the new one
// XXX - convert name to device name, using audio config file
// Check the file. If non-existent, give up.
return (AUDIO_UNIXERROR);
}
// If not a character file, stop right there
return (AUDIO_ERR_NOTDEVICE);
// Open the file and check that it's an audio file
if (desc < 0) {
return (AUDIO_ERR_DEVICEBUSY);
} else {
return (AUDIO_UNIXERROR);
}
}
// Set the file descriptor (this marks the file open)
if (err != AUDIO_SUCCESS) {
setfd(-1);
return (err);
}
// Get the device type
// Set up the cached versions of the current encoding format
(void) GetWriteHeader();
(void) GetReadHeader();
// Set the appropriate blocking/non-blocking mode
return (AUDIO_SUCCESS);
}
// Read data from device into specified buffer.
// No data format translation takes place.
// Since there's no going back, the object's read position pointer is updated.
void* buf, // destination buffer address
{
// Call the real routine
// XXX - Check for bug 1100839: short blocking reads
if (GetBlocking()) {
goto tryagain;
if (len == 0) {
AUDIO_DEBUG((1,
"AudioDevice: zero-length blocking read\n"));
goto tryagain;
} else {
AUDIO_DEBUG((1,
"AudioDevice: short blocking read: %d/%d\n",
}
}
}
// Update the object's read position
if (!err)
return (err);
}
// Write data to device from specified buffer.
// No data format translation takes place.
// Since there's no going back, the object's write position pointer is updated.
void* buf, // source buffer address
{
// Call the real routine
// Update the object's write position
if (err == AUDIO_SUCCESS)
return (err);
}
// Write eof sync flag
WriteEof()
{
if (!opened())
// Make sure the device is set to blocking mode
if (!(EOFblock = GetBlocking()))
// A zero-length write represents an EOF marker
// A failed non-blocking request should never happen!
} else {
}
}
// Restore blocking mode
if (!EOFblock)
return (RaiseError(err));
}
// Flush all queued input and output
const FileAccess which)
{
int flag;
if (!opened())
flag = 0;
return (RaiseError(AUDIO_UNIXERROR));
// Back up the object's write position
}
}
return (AUDIO_SUCCESS);
}
// Wait for output to drain
{
if (!opened())
// If interrupted system call while fd is set blocking, retry
continue;
return (RaiseError(AUDIO_UNIXERROR));
}
return (AUDIO_SUCCESS);
}
const FileAccess which)
{
}
const FileAccess which)
{
}
// Set play eof count
unsigned& cnt)
{
if (err == AUDIO_SUCCESS)
return (err);
}
// Set play sample count
unsigned& cnt)
{
if (err == AUDIO_SUCCESS)
return (err);
}
// Set record sample count
unsigned& cnt)
{
if (err == AUDIO_SUCCESS)
return (err);
}
// Set play error flag, returning old state
{
if (err == AUDIO_SUCCESS)
return (err);
}
// Set record error flag, returning old state
{
if (err == AUDIO_SUCCESS)
return (err);
}
// Set record input buffer delay, returning new value
{
unsigned int d;
if (err != AUDIO_SUCCESS)
return (err);
}
// Set Play-Waiting flag
{
}
// Set Record-Waiting flag
{
}
// Scale an integer gain level to floating point (0. to 1.)
unsigned int val) // gain value
{
}
// Rescale a floating point level to the correct gain
unsigned int AudioDevice::
{
+ AUDIO_MIN_GAIN);
}
// Scale an integer balance level to floating point (-1. to 1.)
unsigned int val) // balance value
{
}
// Rescale a floating point level to the correct balance
unsigned int AudioDevice::
{
}
// Raise or lower a gain field by one notch
unsigned int *field) // ptr to gain field in info
{
int incr;
unsigned int oldval;
int val;
// Get the starting point
if (err != AUDIO_SUCCESS)
return (err);
// If we're already at the min or max, do nothing
if (up) {
if (oldval == AUDIO_MAX_GAIN)
return (AUDIO_SUCCESS);
incr = 1;
} else {
if (oldval == AUDIO_MIN_GAIN)
return (AUDIO_SUCCESS);
incr = -1;
}
if (err != AUDIO_SUCCESS)
return (err);
break; // the value changed!
}
return (AUDIO_SUCCESS);
}
// Set Play volume
{
return (err);
}
// Raise volume a notch
{
}
// Lower volume a notch
{
}
// Record volume
{
return (err);
}
// Raise volume a notch
{
}
// Lower volume a notch
{
}
// Monitor volume
{
return (err);
}
// Raise volume a notch
{
}
// Lower volume a notch
{
}
// Set balance
{
return (err);
}
// Set balance
{
return (err);
}
// Get Play volume
{
if (uinfo == 0) {
} else {
}
}
// Get Record volume
{
if (uinfo == 0) {
} else {
}
}
// Get Monitor volume
{
if (uinfo == 0) {
} else {
}
}
// Get Play balance
{
if (uinfo == 0) {
} else {
}
}
// Get Record balance
{
if (uinfo == 0) {
} else {
}
}
// Get play sample count
unsigned AudioDevice::
{
if (uinfo == 0) {
return (AUDIO_UNKNOWN_SIZE);
} else {
}
}
// Get record sample count
unsigned AudioDevice::
{
if (uinfo == 0) {
return (AUDIO_UNKNOWN_SIZE);
} else {
}
}
// Get Play-Open flag
{
if (uinfo == 0) {
return (TRUE);
} else {
return (TRUE);
}
return (FALSE);
}
// Get Record-Open flag
{
if (uinfo == 0) {
return (TRUE);
} else {
return (TRUE);
}
return (FALSE);
}
// Get Play-Waiting flag
{
if (uinfo == 0) {
return (TRUE);
} else {
return (TRUE);
}
return (FALSE);
}
// Get Record-Waiting flag
{
if (uinfo == 0) {
return (TRUE);
} else {
return (TRUE);
}
return (FALSE);
}