root/usr/src/cmd/audio/utilities/AudioPipe.cc
/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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) 1990-2001 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#include <stdlib.h>
#include <unistd.h>
#include <AudioPipe.h>

// class AudioPipe methods


// Constructor with file descriptor, mode, and optional name
AudioPipe::
AudioPipe(
        const int               desc,           // file descriptor
        const FileAccess        acc,            // access mode
        const char              *name_local):   // name
        AudioUnixfile(name_local, acc)
{
        setfd(desc);
}

// The create routine for pipes writes a file header
AudioError AudioPipe::
Create()
{
        AudioError      err;

        // Was the header properly set?
        err = GetHeader().Validate();
        if (err != AUDIO_SUCCESS)
                return (RaiseError(err));

        // Open fd supplied by constructor
        if (!isfdset())
                return (RaiseError(AUDIO_ERR_NOEFFECT));

        // Write the file header with current (usually unknown) size
        err = encode_filehdr();
        if (err != AUDIO_SUCCESS) {
                (void) close(getfd());          // If error, remove file
                setfd(-1);
                return (err);
        }

        // Set the actual output length to zero
        setlength(0.);

        return (AUDIO_SUCCESS);
}

// The open routine for pipes decodes the header
AudioError AudioPipe::
Open()
{
        AudioError              err;

        // The constructor should have supplied a valid fd
        if (!isfdset())
                return (RaiseError(AUDIO_ERR_NOEFFECT));

        // Decode a file header
        err = decode_filehdr();
        if (err != AUDIO_SUCCESS) {
                (void) close(getfd());
                setfd(-1);
                return (err);
        }

        return (AUDIO_SUCCESS);
}

// Read data from underlying pipe into specified buffer.
// No data format translation takes place.
// Since there's no going back, the object's read position pointer is updated.
AudioError AudioPipe::
ReadData(
        void*           buf,            // destination buffer address
        size_t&         len,            // buffer length (updated)
        Double&         pos)            // start position (updated)
{
        AudioError      err;
        char            *tbuf;          // current buffer pointer
        size_t          remain;         // number of bytes remaining
        size_t          cnt;            // accumulated number of bytes read

        tbuf = (char *)buf;
        remain = len;
        cnt = 0;

        // Pipes return short reads.  If non-blocking i/o, try to read all.
        do {
                // Call the real routine
                err = AudioUnixfile::ReadData((void*)tbuf, remain, pos);

                // Update the object's read position
                if (!err) {
                        (void) SetReadPosition(pos, Absolute);
                        if (remain == 0)
                                break;
                        cnt += remain;
                        tbuf += remain;
                        remain = len - cnt;
                }
        } while (!err && (remain > 0) && GetBlocking());
        len = cnt;
        if (len > 0)
                return (AUDIO_SUCCESS);
        return (err);
}

// Write data to underlying file from specified buffer.
// No data format translation takes place.
// Since there's no going back, the object's write position pointer is updated.
AudioError AudioPipe::
WriteData(
        void*           buf,            // source buffer address
        size_t&         len,            // buffer length (updated)
        Double&         pos)            // start position (updated)
{
        AudioError      err;

        // Call the real routine
        err = AudioUnixfile::WriteData(buf, len, pos);

        // Update the object's write position
        if (err == AUDIO_SUCCESS)
                (void) SetWritePosition(pos, Absolute);
        return (err);
}