/*
* 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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <string.h>
#include <fcntl.h>
#include <AudioFile.h>
#include <AudioLib.h>
#include <AudioDebug.h>
#include <libaudio.h>
#include <audio_hdr.h>
// class AudioFile methods
// Initialize temporary file params
// Initialize default access mode, used when a filename is supplied
// Default audio file path prefix environment variable
AudioFile():
{
}
// Constructor with pathname and optional mode arg
const char *path, // filename
{
}
// Destructor must call the local Close() routine
~AudioFile()
{
// If the file was open, close it
if (opened())
(void) Close();
}
// Set a default temporary file directory
const char *path)
{
// Verify intended path
return (AUDIO_UNIXERROR);
}
return (AUDIO_SUCCESS);
}
// Create a named file according to the current mode setting
const char *path) // pathname or 0
{
char *tmpf;
char *tmpstr;
int openmode;
int desc;
// Convert the open mode to an int argument for open()
// Was the header properly set?
if (!hdrset())
return (RaiseError(AUDIO_ERR_BADHDR));
// Can't create if already opened or if mode or name not set
return (RaiseError(AUDIO_ERR_NOEFFECT));
// If temporary file, create and unlink it.
// Construct the temporary file path
// Open the temp file and unlink it
(void) Close();
}
return (err);
}
// Create the file
(char *)"Large File"));
} else if (desc < 0) {
return (RaiseError(AUDIO_UNIXERROR));
}
// Set the file descriptor (this marks the file open)
// Write the file header with current (usually unknown) size
err = encode_filehdr();
if (err != AUDIO_SUCCESS) {
setfd(-1);
return (err);
}
// Save the length that got written, then set it to zero
setlength(0.);
// Set the size of the file header
if (hdrsize < 0) {
setfd(-1);
return (err);
}
seekpos = 0;
return (AUDIO_SUCCESS);
}
// Create a file whose name is already set, according to the mode setting
Create()
{
return (createfile(GetName()));
}
// Open a file whose name is set
Open()
{
}
// Open a file, using the specified path prefixes
const char *path)
{
char *filename;
int flen;
char *prefix;
char *str;
char *wrk;
char *pathname;
int openmode;
// Convert the open mode to an int argument for open()
// Can't open if already opened or if mode or name not set
return (RaiseError(AUDIO_ERR_NOEFFECT));
// Search path:
// 1) try name: if not found and not readonly:
// if Append mode, try creating it
// 2) if name is a relative pathname, and 'path' is not NULL:
// try every path prefix in 'path'
if (!err)
return (AUDIO_SUCCESS);
// If file is non-existent and Append mode, try creating it.
return (Create());
}
return (RaiseError(err));
}
// Try path as an environment variable name, else assume it is a path
// Make a copy of the path, to parse it
// Try each component as a path prefix
*str++ = '\0';
delete pathname;
switch (err) {
case AUDIO_SUCCESS: // found the file
delete wrk;
return (RaiseError(err));
// XXX - if file found but not audio, stop looking??
}
}
delete wrk;
}
// Can't find file. Return the original error condition.
}
// Attempt to open the given audio file
const char *pathname,
int openmode)
{
int desc;
// If the name is changing, set the new one
// Does the file exist?
return (AUDIO_UNIXERROR);
// If not a regular file, stop right there
return (AUDIO_ERR_BADFILEHDR);
// Open the file and check that it's an audio file
(char *)"Large File"));
} else if (desc < 0) {
return (AUDIO_UNIXERROR);
}
// Set the file descriptor (this marks the file open)
err = decode_filehdr();
if (err != AUDIO_SUCCESS) {
setfd(-1);
return (err);
}
// Save the length of the data and the size of the file header
if (hdrsize < 0) {
setfd(-1);
return (err);
}
seekpos = 0;
// If this is ReadOnly file, mmap() it. Don't worry if mmap() fails.
/*
* Can't mmap LITTLE_ENDIAN as they are converted in
* place.
*/
if (localByteOrder() == BIG_ENDIAN) {
// set default access method
(int)GetAccessType());
} else {
(char *)"Could not mmap() file");
mapaddr = 0;
maplen = 0;
}
} else {
mapaddr = 0;
maplen = 0;
}
}
return (AUDIO_SUCCESS);
}
// set VM access hint for mmapped files
{
if (!opened()) {
return (AUDIO_ERR_NOEFFECT);
}
if (mapaddr == 0) {
return (AUDIO_ERR_NOEFFECT);
}
return (AUDIO_SUCCESS);
}
// Close the file
Close()
{
if (!opened())
// Rewind the file and rewrite the header with the correct length
// sanity check
"AudioFile:Close()...inconsistent length\n"),
Fatal);
}
// XXX - should be rewritten in C++
}
// Call the generic file close routine
if (mapaddr) {
mapaddr = 0;
maplen = 0;
}
// Init important values, in case the file is reopened
hdrsize = 0;
seekpos = 0;
return (RaiseError(err));
}
// Read data from underlying file into specified buffer.
// No data format translation takes place.
// The object's read position pointer is unaffected.
void* buf, // destination buffer address
{
// If the file is not mapped, call parent ReadData() and return
if (mapaddr == 0) {
// Call the real routine
// Update the cached seek pointer
return (err);
}
// If the file is mmapped, do a memcpy() from the mapaddr
// 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));
// Make sure we don't read off the end of file
// trying to read past EOF
return (err);
// re-adjust cnt so it reads up to the end of file
}
// Zero-length reads are finished
err = AUDIO_SUCCESS;
return (err);
} else {
}
// Return the updated byte count and position
// Check to see if the endian is right. Note that special care
// doesn't need to be taken because of the mmap, since the data
// is copied into a separate buffer anyway.
return (AUDIO_SUCCESS);
}
// Write data to underlying file from specified buffer.
// No data format translation takes place.
// The object's write position pointer is unaffected.
void* buf, // source buffer address
{
// Call the real routine
// Update the cached seek pointer
return (err);
}
// Set the Unix file pointer to match a given file position.
{
}
return (AUDIO_SUCCESS);
}
// Set the Unix file pointer to match a given file position.
// If seek beyond end-of-file, NULL out intervening data.
{
// If append-only, can't seek backwards into file
// If seek beyond eof, fill data
// XXX - not implemented yet
return (AUDIO_SUCCESS);
}
}
return (AUDIO_SUCCESS);
}
// Copy routine that handles mapped files
{
// If this is NOT mmapped, or the destination is an AudioBuffer,
// use the default routine
}
return (err);
if (limit < 0.)
return (RaiseError(AUDIO_ERR_BADARG));
// Get maximum possible copy length
limit = 0.;
return (err);
}
limit = 0.;
// trying to read past EOF
return (err);
// re-adjust cnt so it reads up to the end of file
}
// Zero-length reads are done
err = AUDIO_SUCCESS;
return (err);
}
// Report short writes
return (err);
}