/*
* 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 1993-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <unistd.h>
#include <AudioDebug.h>
#include <AudioUnixfile.h>
#include <libaudio.h>
#include <audio_hdr.h>
// class AudioUnixfile methods
// Constructor with pathname and mode arg
const char *path, // pathname
{
infostring[0] = '\0';
}
// Destructor
{
// If the file is open, close it
if (opened())
(void) Close();
// Deallocate the dynamic storage
delete infostring;
}
// Generic open with search path routine just calls default Open()
const char *)
{
return (Open());
}
// Decode an audio file header
// This routine reads the audio file header and decodes it.
//
// This method should be specialized by subclasses that are not files,
// like devices for instance.
//
// XXX - this routine should be rewritten for C++
{
char *ibuf;
int file_type;
int infosize;
int cnt;
// If fd is not open, or file header already decoded, skip it
// Stat the file, to see if it is a regular file
return (RaiseError(AUDIO_UNIXERROR));
// Make sure the file is not set for blocking i/o
saveblock = GetBlocking();
if (!saveblock)
// Read the file header, but not the info field
// XXX - Should use C++ input method
return (RaiseError(AUDIO_UNIXERROR));
}
// Check the validity of the header and get the size of the info field
if (err != AUDIO_SUCCESS)
return (RaiseError(err));
// Allocate and read in the info field
delete ibuf;
return (RaiseError(AUDIO_UNIXERROR));
}
// XXX - convert from libaudio header
// big endian.
if (err != AUDIO_SUCCESS) {
delete ibuf;
return (RaiseError(err));
}
delete ibuf;
// Only trust the file size for regular files
// Sanity check
// always consider it to be unknown if not reading a real file
// since there's no real way to verify if the header is
// correct.
} else {
}
// set flag for opened() test
filehdrset = TRUE;
return (AUDIO_SUCCESS);
}
// Write an audio file header
// This routine encodes the audio file header and writes it out.
// XXX - It assumes that the file pointer is set to the start of the file.
//
// This method should be specialized by subclasses that are not files,
// like devices for instance.
//
// XXX - this routine should be rewritten for C++
{
// If fd is not open, or file header already written, skip it
// XXX - Set up the libaudio hdr
if (err != AUDIO_SUCCESS) {
return (RaiseError(err));
}
else
/* Make sure the file is not set for blocking i/o */
saveblock = GetBlocking();
if (!saveblock)
// XXX - Should use C++ output method
// set flag for opened() test
if (err == AUDIO_SUCCESS)
filehdrset = TRUE;
return (RaiseError(err));
}
// Set a file blocking/non-blocking
// This method should be subclassed by objects that always block (eg, files)
void AudioUnixfile::
Boolean b) // FALSE to set non-blocking
{
int flag;
// If the file is open, set blocking/non-blocking now
if (isfdset()) {
(char *)"Large File");
} else if (b) {
} else {
}
}
}
// Set the blocking flag (this may affect the Open() behavior)
block = b;
}
// Return a pointer to the info string
// XXX - returns a pointer to the string stored in the object
// XXX - assumes ASCII data
char *const AudioUnixfile::
int& len) const // returned length of string
{
len = infolength;
return (infostring);
}
// Set the info string
void AudioUnixfile::
const char *str, // new info string
int len) // length of string
{
// If length defaulted, assume an ASCII string
if (len == -1)
delete infostring;
infostring = new char[len];
infolength = len;
}
// Close file
Close()
{
// If the file is open, close it
if (isfdset()) {
return (RaiseError(AUDIO_UNIXERROR));
} else {
}
// Init important values, in case the file is reopened
setfd(-1);
filehdrset = FALSE;
return (AUDIO_SUCCESS);
}
// Read data from underlying file into specified buffer.
// No data format translation takes place.
// The object's read position is not updated (subclasses can change this)
void* buf, // destination buffer address
{
// Save buffer size and zero transfer count
len = 0;
// Cannot read if file is not open
return (RaiseError(AUDIO_ERR_NOEFFECT));
// Position must be valid
return (RaiseError(AUDIO_ERR_BADARG));
// Position the file pointer to the right place
if (err != AUDIO_SUCCESS)
return (err);
// Check for EOF
return (err);
}
// Zero-length reads are finished
err = AUDIO_SUCCESS;
return (err);
}
// Read as much data as possible
if (cnt < 0) {
perror("read");
exit(1);
!GetBlocking())) {
// Is this an interrupted or failed non-blocking request?
err = AUDIO_SUCCESS;
return (err);
}
return (RaiseError(AUDIO_UNIXERROR));
}
// End-of-file?
if ((cnt == 0) && GetBlocking()) {
AUDIO_DEBUG((1,
}
return (err);
}
err = AUDIO_SUCCESS;
if (cnt == 0) {
}
// Return the updated byte count and position
AUDIO_DEBUG((1,
"Read returned a partial sample frame?!\n"));
}
// Check to see if the endian is right.
return (err);
}
// Write data to underlying file from specified buffer.
// No data format translation takes place.
// The object's write position is not updated (subclasses can change this)
void* buf, // source buffer address
{
// Save buffer size and zero transfer count
len = 0;
// Cannot write if file is not open
return (RaiseError(AUDIO_ERR_NOEFFECT));
// Position must be valid
return (RaiseError(AUDIO_ERR_BADARG));
// Zero-length writes are easy
err = AUDIO_SUCCESS;
return (err);
}
// Position the file pointer to the right place
if (err != AUDIO_SUCCESS)
return (err);
// Make sure data is in target's endian format before writing.
// This conversion is done inplace so we need to change back.
// We assume that the data in buf is in localByteOrder.
// Only files should have order issues.
// Write as much data as possible
err = AUDIO_SUCCESS;
if (cnt < 0) {
perror("write");
exit(1);
// Is this a failed non-blocking request?
return (err);
}
return (RaiseError(AUDIO_UNIXERROR));
}
if (cnt == 0)
// Switch the endian back if local order doesn't match target order.
// Return the updated byte count and position
// If the current position is beyond old EOF, update the size
}
return (AUDIO_SUCCESS);
}
// Seek in input stream
// Ordinary streams (ie, pipes and devices) cannot be rewound.
// A forward seek in them consumes data by reading it.
//
// This method should be specialized by subclasses that can actually seek,
// like regular files for instance.
//
{
pos -= ReadPosition();
// If the seek is backwards, do nothing
if (pos < 0.)
// If the seek is to the current position, then do nothing.
if (icnt == 0)
return (AUDIO_SUCCESS);
// The seek is determinate and forward.
// We'll have to consume data to get there.
// First allocate a buffer to stuff the data into.
// Then set the stream for blocking i/o (saving the old state).
if (bufp == 0) { // allocation error, try a smaller buf
if (bufp == 0)
return (RaiseError(AUDIO_UNIXERROR));
}
// XXX - May have to realign to partial frame count!
saveblock = GetBlocking();
if (!saveblock)
// Loop until the seek is satisfied (or an error occurs).
do {
// Limit the read to keep from going too far
if (err != AUDIO_SUCCESS)
break;
} while (icnt > 0);
delete bufp; // Free the temporary buffer
return (RaiseError(err));
}
// Seek in output stream
// Ordinary streams (ie, pipes and devices) cannot be rewound.
// A forward seek in them writes NULL data.
//
// This method should be specialized by subclasses that can actually seek,
// like regular files for instance.
//
{
pos -= WritePosition();
// If the seek is backwards, do nothing
if (pos < 0.)
// If the seek is to the current position, then do nothing.
if (ocnt == 0)
return (AUDIO_SUCCESS);
// The seek is determinate and forward.
// We'll have to produce NULL data to get there.
// XXX - not implemented correctly yet
if (bufp == 0) { // allocation error, try a smaller buf
if (bufp == 0)
return (RaiseError(AUDIO_UNIXERROR));
}
// XXX - May have to realign to partial frame count!
saveblock = GetBlocking();
if (!saveblock)
// Loop until the seek is satisfied (or an error occurs).
do {
// Limit the write to keep from going too far
if (err != AUDIO_SUCCESS)
break;
} while (ocnt > 0);
delete bufp; // Free the temporary buffer
return (RaiseError(err));
}