Audio.cc revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 (c) 1993-2001 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <Audio.h>
#include <AudioDebug.h>
#include <AudioBuffer.h>
// class Audio methods
// Initialize monotonically increasing id counter
int
// Constructor
Audio::
const char *str): // name
{
char *s;
#ifndef DEBUG
// errorfunc is always set if compiling DEBUG;
// otherwise, only if requested
if (GetDebug() > 0)
#endif
}
// Destructor
Audio::
~Audio()
{
// If there are outstanding references, there is a programming error
if (refcnt < 0) {
} else if (refcnt > 0) {
} else {
refcnt = -1;
}
delete name;
}
// Raise error code
char *msg) const // additional message
{
if (code == AUDIO_SUCCESS)
return (code);
if (errorfunc != 0) {
// XXX - Userfunc return value ignored for now
}
abort();
return (code);
}
// Print out messages
void Audio::
char *msg, // error message
{
if (errorfunc != 0) {
// XXX - Userfunc return value ignored for now
}
abort();
}
}
// Increment reference count
void Audio::
{
if (refcnt < 0) {
} else {
refcnt++;
}
}
// Decrement reference count
void Audio::
{
if (refcnt < 0) {
Fatal);
} else if (refcnt == 0) {
} else if (--refcnt == 0) { // If this was the last reference,
delete this; // blow the object away
}
}
// Reset the stored name
void Audio::
const char *str) // new name string
{
delete name;
}
Whence w) // Absolute || Relative || Relative_eof
{
if (w == Relative) // offset from current position
else if (w == Relative_eof) { // offset from end-of-file
else
return (AUDIO_UNKNOWN_TIME);
}
// If seek before start of file, set to start of file
if (newpos < 0.)
newpos = 0.;
return (pos);
}
// Set a new read position
Whence w) // Absolute | Relative
{
}
// Set a new write position
Whence w) // Absolute | Relative
{
}
// Default read routine reads from the current position
Read(
void* buf, // buffer address
{
// ReadData updates the position argument
}
// Default write routine writes to the current position
void* buf, // buffer address
{
// WriteData updates the position argument
}
// Default append routine should be specialized, if the object is fixed-length
void* buf, // buffer address
{
// The default action is just to write the data.
// Subclasses, like AudioBuffer, should specialize this method
// to extend the object, if necessary.
}
// Copy out to the specified audio object.
// Input and output positions default to the 'current' positions.
Copy(
{
}
// Default Copy out routine. Specify the destination audio object,
// AUDIO_UNKNOWN_TIME to copy to eof or error.
// frompos and topos are updated with the final positions.
// limit is updated with the amount of data actually copied.
Copy(
{
// If positions are Undefined, try to set them properly
frompos = ReadPosition();
do {
// Calculate remaining copy size
} else {
if (len < 0.)
len = 0.;
}
// Copy one segment
if (!err) {
default:
case 0:
break;
// XXX - What do we do with short writes?
// This routine is meant to block until all the
// data has been copied. So copies to a pipe or
// device should continue. However, copies to a
// buffer (or extent or list?) will never go any
// further.
// For now, punt and return immediately.
case AUDIO_COPY_SHORT_OUTPUT:
goto outofloop;
// If a zero-length transfer was requested, we're done
case AUDIO_COPY_ZERO_LIMIT:
goto outofloop;
// If the input would block, we're done
case AUDIO_COPY_SHORT_INPUT:
goto outofloop;
}
}
} while (err == AUDIO_SUCCESS);
// Calculate total transfer count
// Declare victory if anything was copied
if (limit > 0.)
return (AUDIO_SUCCESS);
return (err);
}
// Default Data Copy out routine. Like Copy(), but only does one segment.
// If either src or dest are set non-blocking, a partial transfer may occur.
// Returns AUDIO_SUCCESS on normal completion, regardless of how much data
// was actually transferred (err.sys: AUDIO_COPY_SHORT_INPUT if input would
// block; AUDIO_COPY_ZERO_LIMIT if a zero-length copy was requested).
// Returns AUDIO_SUCCESS (err.sys: AUDIO_COPY_SHORT_OUTPUT) if more data was
// read than could be copied out (eg, if there was a short write to a
// non-blocking output). Short writes result in the input pointer being
// backed up to the right place in the input stream.
// Returns AUDIO_EOF if input or output position beyond end-of-file.
//
// XXX - If the input cannot seek backwards, this routine will spin trying
// to finish writing all input data to the output. We need to keep
// partial data in a state structure.
{
// Validate basic arguments and state
return (err);
if (limit < 0.)
return (RaiseError(AUDIO_ERR_BADARG));
// If the destination is an AudioBuffer, we can copy more directly
// Get the buffer address at the starting offset
limit = 0.;
return (err);
}
// Limit the data transfer by the limit argument
// Read the data directly into buffer
return (err);
}
// XXX - temporary bogus implementation
// XXX - max transfer buf will be 2 seconds of data (1 sec for stereo)
} else {
}
limit = 0.;
return (AUDIO_UNIXERROR);
if (!err) {
AUDIO_DEBUG((1,
"Read returned a fraction of a sample frame?!\n"));
}
if (bufsiz > 0) {
// If the write was short, back up the input pointer
AUDIO_DEBUG((1,
"Write returned a fraction of a sample frame?!\n"));
}
if (!err)
}
}
}
delete bptr;
return (err);
}