1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1993-2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <string.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <stdio.h> 32*7c478bd9Sstevel@tonic-gate #include <Audio.h> 33*7c478bd9Sstevel@tonic-gate #include <AudioDebug.h> 34*7c478bd9Sstevel@tonic-gate #include <AudioBuffer.h> 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate // class Audio methods 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate // Initialize monotonically increasing id counter 40*7c478bd9Sstevel@tonic-gate int 41*7c478bd9Sstevel@tonic-gate Audio::idctr = 0; 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate // Constructor 44*7c478bd9Sstevel@tonic-gate Audio:: 45*7c478bd9Sstevel@tonic-gate Audio( 46*7c478bd9Sstevel@tonic-gate const char *str): // name 47*7c478bd9Sstevel@tonic-gate id(++idctr), refcnt(0), readpos(0.), writepos(0.), errorfunc(0) 48*7c478bd9Sstevel@tonic-gate { 49*7c478bd9Sstevel@tonic-gate char *s; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate s = (char *)((str == NULL) ? "" : str); 52*7c478bd9Sstevel@tonic-gate name = new char[strlen(s) + 1]; 53*7c478bd9Sstevel@tonic-gate (void) strcpy(name, s); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #ifndef DEBUG 56*7c478bd9Sstevel@tonic-gate // errorfunc is always set if compiling DEBUG; 57*7c478bd9Sstevel@tonic-gate // otherwise, only if requested 58*7c478bd9Sstevel@tonic-gate if (GetDebug() > 0) 59*7c478bd9Sstevel@tonic-gate #endif 60*7c478bd9Sstevel@tonic-gate errorfunc = AudioStderrMsg; 61*7c478bd9Sstevel@tonic-gate PrintMsg(_MGET_("Audio object create"), InitMessage); 62*7c478bd9Sstevel@tonic-gate } 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate // Destructor 65*7c478bd9Sstevel@tonic-gate Audio:: 66*7c478bd9Sstevel@tonic-gate ~Audio() 67*7c478bd9Sstevel@tonic-gate { 68*7c478bd9Sstevel@tonic-gate // If there are outstanding references, there is a programming error 69*7c478bd9Sstevel@tonic-gate if (refcnt < 0) { 70*7c478bd9Sstevel@tonic-gate PrintMsg(_MGET_("Audio object multiple destroy"), InitFatal); 71*7c478bd9Sstevel@tonic-gate } else if (refcnt > 0) { 72*7c478bd9Sstevel@tonic-gate PrintMsg(_MGET_("Referenced Audio object destroyed"), 73*7c478bd9Sstevel@tonic-gate InitFatal); 74*7c478bd9Sstevel@tonic-gate } else { 75*7c478bd9Sstevel@tonic-gate refcnt = -1; 76*7c478bd9Sstevel@tonic-gate PrintMsg(_MGET_("Audio object destroy"), InitMessage); 77*7c478bd9Sstevel@tonic-gate } 78*7c478bd9Sstevel@tonic-gate delete name; 79*7c478bd9Sstevel@tonic-gate } 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate // Raise error code 82*7c478bd9Sstevel@tonic-gate AudioError Audio:: 83*7c478bd9Sstevel@tonic-gate RaiseError( 84*7c478bd9Sstevel@tonic-gate AudioError code, // error code 85*7c478bd9Sstevel@tonic-gate AudioSeverity sev, // error severity 86*7c478bd9Sstevel@tonic-gate char *msg) const // additional message 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate if (code == AUDIO_SUCCESS) 89*7c478bd9Sstevel@tonic-gate return (code); 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate if (errorfunc != 0) { 92*7c478bd9Sstevel@tonic-gate // XXX - Userfunc return value ignored for now 93*7c478bd9Sstevel@tonic-gate (void) (*errorfunc)(this, code, sev, msg); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate if ((sev == Fatal) || (sev == InitFatal)) 96*7c478bd9Sstevel@tonic-gate abort(); 97*7c478bd9Sstevel@tonic-gate return (code); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate // Print out messages 101*7c478bd9Sstevel@tonic-gate void Audio:: 102*7c478bd9Sstevel@tonic-gate PrintMsg( 103*7c478bd9Sstevel@tonic-gate char *msg, // error message 104*7c478bd9Sstevel@tonic-gate AudioSeverity sev) const // error severity 105*7c478bd9Sstevel@tonic-gate { 106*7c478bd9Sstevel@tonic-gate if (errorfunc != 0) { 107*7c478bd9Sstevel@tonic-gate // XXX - Userfunc return value ignored for now 108*7c478bd9Sstevel@tonic-gate (void) (*errorfunc)(this, AUDIO_NOERROR, sev, msg); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate if ((sev == Fatal) || (sev == InitFatal)) { 112*7c478bd9Sstevel@tonic-gate fprintf(stderr, _MGET_("** Fatal Error: %s\n"), msg); 113*7c478bd9Sstevel@tonic-gate abort(); 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate // Increment reference count 118*7c478bd9Sstevel@tonic-gate void Audio:: 119*7c478bd9Sstevel@tonic-gate Reference() 120*7c478bd9Sstevel@tonic-gate { 121*7c478bd9Sstevel@tonic-gate if (refcnt < 0) { 122*7c478bd9Sstevel@tonic-gate PrintMsg(_MGET_("Reference to destroyed Audio object"), Fatal); 123*7c478bd9Sstevel@tonic-gate } else { 124*7c478bd9Sstevel@tonic-gate refcnt++; 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate // Decrement reference count 129*7c478bd9Sstevel@tonic-gate void Audio:: 130*7c478bd9Sstevel@tonic-gate Dereference() 131*7c478bd9Sstevel@tonic-gate { 132*7c478bd9Sstevel@tonic-gate if (refcnt < 0) { 133*7c478bd9Sstevel@tonic-gate PrintMsg(_MGET_("Dereference of destroyed Audio object"), 134*7c478bd9Sstevel@tonic-gate Fatal); 135*7c478bd9Sstevel@tonic-gate } else if (refcnt == 0) { 136*7c478bd9Sstevel@tonic-gate PrintMsg(_MGET_("Audio object dereference underflow"), Fatal); 137*7c478bd9Sstevel@tonic-gate } else if (--refcnt == 0) { // If this was the last reference, 138*7c478bd9Sstevel@tonic-gate delete this; // blow the object away 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate // Reset the stored name 143*7c478bd9Sstevel@tonic-gate void Audio:: 144*7c478bd9Sstevel@tonic-gate SetName( 145*7c478bd9Sstevel@tonic-gate const char *str) // new name string 146*7c478bd9Sstevel@tonic-gate { 147*7c478bd9Sstevel@tonic-gate delete name; 148*7c478bd9Sstevel@tonic-gate name = new char[strlen(str) + 1]; 149*7c478bd9Sstevel@tonic-gate (void) strcpy(name, str); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate // Set the current read/write position pointer 154*7c478bd9Sstevel@tonic-gate Double Audio:: 155*7c478bd9Sstevel@tonic-gate setpos( 156*7c478bd9Sstevel@tonic-gate Double& pos, // field to update 157*7c478bd9Sstevel@tonic-gate Double newpos, // new position 158*7c478bd9Sstevel@tonic-gate Whence w) // Absolute || Relative || Relative_eof 159*7c478bd9Sstevel@tonic-gate { 160*7c478bd9Sstevel@tonic-gate if (w == Relative) // offset from current position 161*7c478bd9Sstevel@tonic-gate newpos += pos; 162*7c478bd9Sstevel@tonic-gate else if (w == Relative_eof) { // offset from end-of-file 163*7c478bd9Sstevel@tonic-gate if (!Undefined(GetLength())) 164*7c478bd9Sstevel@tonic-gate newpos += GetLength(); 165*7c478bd9Sstevel@tonic-gate else 166*7c478bd9Sstevel@tonic-gate return (AUDIO_UNKNOWN_TIME); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate // If seek before start of file, set to start of file 170*7c478bd9Sstevel@tonic-gate if (newpos < 0.) 171*7c478bd9Sstevel@tonic-gate newpos = 0.; 172*7c478bd9Sstevel@tonic-gate pos = newpos; 173*7c478bd9Sstevel@tonic-gate return (pos); 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate // Set a new read position 177*7c478bd9Sstevel@tonic-gate Double Audio:: 178*7c478bd9Sstevel@tonic-gate SetReadPosition( 179*7c478bd9Sstevel@tonic-gate Double pos, // new position or offset 180*7c478bd9Sstevel@tonic-gate Whence w) // Absolute | Relative 181*7c478bd9Sstevel@tonic-gate { 182*7c478bd9Sstevel@tonic-gate return (setpos(readpos, pos, w)); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate // Set a new write position 186*7c478bd9Sstevel@tonic-gate Double Audio:: 187*7c478bd9Sstevel@tonic-gate SetWritePosition( 188*7c478bd9Sstevel@tonic-gate Double pos, // new position or offset 189*7c478bd9Sstevel@tonic-gate Whence w) // Absolute | Relative 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate return (setpos(writepos, pos, w)); 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate // Default read routine reads from the current position 195*7c478bd9Sstevel@tonic-gate AudioError Audio:: 196*7c478bd9Sstevel@tonic-gate Read( 197*7c478bd9Sstevel@tonic-gate void* buf, // buffer address 198*7c478bd9Sstevel@tonic-gate size_t& len) // buffer length (updated) 199*7c478bd9Sstevel@tonic-gate { 200*7c478bd9Sstevel@tonic-gate // ReadData updates the position argument 201*7c478bd9Sstevel@tonic-gate return (ReadData(buf, len, readpos)); 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate // Default write routine writes to the current position 205*7c478bd9Sstevel@tonic-gate AudioError Audio:: 206*7c478bd9Sstevel@tonic-gate Write( 207*7c478bd9Sstevel@tonic-gate void* buf, // buffer address 208*7c478bd9Sstevel@tonic-gate size_t& len) // buffer length (updated) 209*7c478bd9Sstevel@tonic-gate { 210*7c478bd9Sstevel@tonic-gate // WriteData updates the position argument 211*7c478bd9Sstevel@tonic-gate return (WriteData(buf, len, writepos)); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate // Default append routine should be specialized, if the object is fixed-length 215*7c478bd9Sstevel@tonic-gate AudioError Audio:: 216*7c478bd9Sstevel@tonic-gate AppendData( 217*7c478bd9Sstevel@tonic-gate void* buf, // buffer address 218*7c478bd9Sstevel@tonic-gate size_t& len, // buffer length (updated) 219*7c478bd9Sstevel@tonic-gate Double& pos) // write position (updated) 220*7c478bd9Sstevel@tonic-gate { 221*7c478bd9Sstevel@tonic-gate // The default action is just to write the data. 222*7c478bd9Sstevel@tonic-gate // Subclasses, like AudioBuffer, should specialize this method 223*7c478bd9Sstevel@tonic-gate // to extend the object, if necessary. 224*7c478bd9Sstevel@tonic-gate return (WriteData(buf, len, pos)); 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate // Copy out to the specified audio object. 228*7c478bd9Sstevel@tonic-gate // Input and output positions default to the 'current' positions. 229*7c478bd9Sstevel@tonic-gate AudioError Audio:: 230*7c478bd9Sstevel@tonic-gate Copy( 231*7c478bd9Sstevel@tonic-gate Audio* to) // audio object to copy to 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate Double frompos = AUDIO_UNKNOWN_TIME; 234*7c478bd9Sstevel@tonic-gate Double topos = AUDIO_UNKNOWN_TIME; 235*7c478bd9Sstevel@tonic-gate Double limit = AUDIO_UNKNOWN_TIME; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate return (Copy(to, frompos, topos, limit)); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate // Default Copy out routine. Specify the destination audio object, 241*7c478bd9Sstevel@tonic-gate // and src/dest start offsets. limit is either the time to copy or 242*7c478bd9Sstevel@tonic-gate // AUDIO_UNKNOWN_TIME to copy to eof or error. 243*7c478bd9Sstevel@tonic-gate // frompos and topos are updated with the final positions. 244*7c478bd9Sstevel@tonic-gate // limit is updated with the amount of data actually copied. 245*7c478bd9Sstevel@tonic-gate AudioError Audio:: 246*7c478bd9Sstevel@tonic-gate Copy( 247*7c478bd9Sstevel@tonic-gate Audio* to, // audio object to copy to 248*7c478bd9Sstevel@tonic-gate Double& frompos, 249*7c478bd9Sstevel@tonic-gate Double& topos, 250*7c478bd9Sstevel@tonic-gate Double& limit) 251*7c478bd9Sstevel@tonic-gate { 252*7c478bd9Sstevel@tonic-gate Double len; 253*7c478bd9Sstevel@tonic-gate Double svpos; 254*7c478bd9Sstevel@tonic-gate AudioError err; 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate // If positions are Undefined, try to set them properly 257*7c478bd9Sstevel@tonic-gate if (Undefined(frompos)) 258*7c478bd9Sstevel@tonic-gate frompos = ReadPosition(); 259*7c478bd9Sstevel@tonic-gate if (Undefined(topos)) 260*7c478bd9Sstevel@tonic-gate topos = to->WritePosition(); 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate svpos = frompos; 263*7c478bd9Sstevel@tonic-gate do { 264*7c478bd9Sstevel@tonic-gate // Calculate remaining copy size 265*7c478bd9Sstevel@tonic-gate if (Undefined(limit)) { 266*7c478bd9Sstevel@tonic-gate len = limit; 267*7c478bd9Sstevel@tonic-gate } else { 268*7c478bd9Sstevel@tonic-gate len = limit - (frompos - svpos); 269*7c478bd9Sstevel@tonic-gate if (len < 0.) 270*7c478bd9Sstevel@tonic-gate len = 0.; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate // Copy one segment 273*7c478bd9Sstevel@tonic-gate err = AsyncCopy(to, frompos, topos, len); 274*7c478bd9Sstevel@tonic-gate if (!err) { 275*7c478bd9Sstevel@tonic-gate switch (err.sys) { 276*7c478bd9Sstevel@tonic-gate default: 277*7c478bd9Sstevel@tonic-gate case 0: 278*7c478bd9Sstevel@tonic-gate break; 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate // XXX - What do we do with short writes? 281*7c478bd9Sstevel@tonic-gate // This routine is meant to block until all the 282*7c478bd9Sstevel@tonic-gate // data has been copied. So copies to a pipe or 283*7c478bd9Sstevel@tonic-gate // device should continue. However, copies to a 284*7c478bd9Sstevel@tonic-gate // buffer (or extent or list?) will never go any 285*7c478bd9Sstevel@tonic-gate // further. 286*7c478bd9Sstevel@tonic-gate // For now, punt and return immediately. 287*7c478bd9Sstevel@tonic-gate case AUDIO_COPY_SHORT_OUTPUT: 288*7c478bd9Sstevel@tonic-gate goto outofloop; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate // If a zero-length transfer was requested, we're done 291*7c478bd9Sstevel@tonic-gate case AUDIO_COPY_ZERO_LIMIT: 292*7c478bd9Sstevel@tonic-gate goto outofloop; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate // If the input would block, we're done 295*7c478bd9Sstevel@tonic-gate case AUDIO_COPY_SHORT_INPUT: 296*7c478bd9Sstevel@tonic-gate goto outofloop; 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate } while (err == AUDIO_SUCCESS); 300*7c478bd9Sstevel@tonic-gate outofloop: 301*7c478bd9Sstevel@tonic-gate // Calculate total transfer count 302*7c478bd9Sstevel@tonic-gate limit = frompos - svpos; 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate // Declare victory if anything was copied 305*7c478bd9Sstevel@tonic-gate if (limit > 0.) 306*7c478bd9Sstevel@tonic-gate return (AUDIO_SUCCESS); 307*7c478bd9Sstevel@tonic-gate return (err); 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate // Default Data Copy out routine. Like Copy(), but only does one segment. 311*7c478bd9Sstevel@tonic-gate // If either src or dest are set non-blocking, a partial transfer may occur. 312*7c478bd9Sstevel@tonic-gate // Returns AUDIO_SUCCESS on normal completion, regardless of how much data 313*7c478bd9Sstevel@tonic-gate // was actually transferred (err.sys: AUDIO_COPY_SHORT_INPUT if input would 314*7c478bd9Sstevel@tonic-gate // block; AUDIO_COPY_ZERO_LIMIT if a zero-length copy was requested). 315*7c478bd9Sstevel@tonic-gate // Returns AUDIO_SUCCESS (err.sys: AUDIO_COPY_SHORT_OUTPUT) if more data was 316*7c478bd9Sstevel@tonic-gate // read than could be copied out (eg, if there was a short write to a 317*7c478bd9Sstevel@tonic-gate // non-blocking output). Short writes result in the input pointer being 318*7c478bd9Sstevel@tonic-gate // backed up to the right place in the input stream. 319*7c478bd9Sstevel@tonic-gate // Returns AUDIO_EOF if input or output position beyond end-of-file. 320*7c478bd9Sstevel@tonic-gate // 321*7c478bd9Sstevel@tonic-gate // XXX - If the input cannot seek backwards, this routine will spin trying 322*7c478bd9Sstevel@tonic-gate // to finish writing all input data to the output. We need to keep 323*7c478bd9Sstevel@tonic-gate // partial data in a state structure. 324*7c478bd9Sstevel@tonic-gate AudioError Audio:: 325*7c478bd9Sstevel@tonic-gate AsyncCopy( 326*7c478bd9Sstevel@tonic-gate Audio* to, // audio object to copy to 327*7c478bd9Sstevel@tonic-gate Double& frompos, 328*7c478bd9Sstevel@tonic-gate Double& topos, 329*7c478bd9Sstevel@tonic-gate Double& limit) 330*7c478bd9Sstevel@tonic-gate { 331*7c478bd9Sstevel@tonic-gate caddr_t bptr; 332*7c478bd9Sstevel@tonic-gate size_t bufsiz; 333*7c478bd9Sstevel@tonic-gate size_t lim; 334*7c478bd9Sstevel@tonic-gate Double svfrom; 335*7c478bd9Sstevel@tonic-gate Double svto; 336*7c478bd9Sstevel@tonic-gate AudioBuffer* tob; 337*7c478bd9Sstevel@tonic-gate AudioHdr tohdr; 338*7c478bd9Sstevel@tonic-gate AudioError err; 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate // Validate basic arguments and state 341*7c478bd9Sstevel@tonic-gate tohdr = to->GetHeader(); 342*7c478bd9Sstevel@tonic-gate if (err = tohdr.Validate()) 343*7c478bd9Sstevel@tonic-gate return (err); 344*7c478bd9Sstevel@tonic-gate if (limit < 0.) 345*7c478bd9Sstevel@tonic-gate return (RaiseError(AUDIO_ERR_BADARG)); 346*7c478bd9Sstevel@tonic-gate lim = (size_t)tohdr.Time_to_Bytes(limit); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate // If the destination is an AudioBuffer, we can copy more directly 349*7c478bd9Sstevel@tonic-gate if (to->isBuffer()) { 350*7c478bd9Sstevel@tonic-gate tob = (AudioBuffer*) to; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate // Get the buffer address at the starting offset 353*7c478bd9Sstevel@tonic-gate bptr = (caddr_t)tob->GetAddress(topos); 354*7c478bd9Sstevel@tonic-gate bufsiz = bptr - (caddr_t)tob->GetAddress(); 355*7c478bd9Sstevel@tonic-gate if ((bptr == NULL) || (tob->GetByteCount() <= bufsiz)) { 356*7c478bd9Sstevel@tonic-gate limit = 0.; 357*7c478bd9Sstevel@tonic-gate err = AUDIO_EOF; 358*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_OUTPUT_EOF; 359*7c478bd9Sstevel@tonic-gate return (err); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate bufsiz = tob->GetByteCount() - bufsiz; 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate // Limit the data transfer by the limit argument 364*7c478bd9Sstevel@tonic-gate if (!Undefined(limit) && (lim < bufsiz)) 365*7c478bd9Sstevel@tonic-gate bufsiz = lim; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate // Read the data directly into buffer 368*7c478bd9Sstevel@tonic-gate (void) tohdr.Bytes_to_Bytes(bufsiz); 369*7c478bd9Sstevel@tonic-gate err = ReadData((void*) bptr, bufsiz, frompos); 370*7c478bd9Sstevel@tonic-gate limit = tohdr.Bytes_to_Time(bufsiz); 371*7c478bd9Sstevel@tonic-gate topos += limit; 372*7c478bd9Sstevel@tonic-gate tob->SetLength(topos); 373*7c478bd9Sstevel@tonic-gate return (err); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate // XXX - temporary bogus implementation 377*7c478bd9Sstevel@tonic-gate // XXX - max transfer buf will be 2 seconds of data (1 sec for stereo) 378*7c478bd9Sstevel@tonic-gate if (tohdr.channels < 2) { 379*7c478bd9Sstevel@tonic-gate bufsiz = (size_t)tohdr.Time_to_Bytes(2.0); 380*7c478bd9Sstevel@tonic-gate } else { 381*7c478bd9Sstevel@tonic-gate bufsiz = (size_t)tohdr.Time_to_Bytes(1.0); 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate if (!Undefined(limit) && (lim < bufsiz)) 384*7c478bd9Sstevel@tonic-gate bufsiz = lim; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate limit = 0.; 387*7c478bd9Sstevel@tonic-gate if ((bptr = new char[bufsiz]) == NULL) 388*7c478bd9Sstevel@tonic-gate return (AUDIO_UNIXERROR); 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate svfrom = frompos; 391*7c478bd9Sstevel@tonic-gate err = ReadData((void*)bptr, bufsiz, frompos); 392*7c478bd9Sstevel@tonic-gate if (!err) { 393*7c478bd9Sstevel@tonic-gate svto = topos; 394*7c478bd9Sstevel@tonic-gate lim = bufsiz; 395*7c478bd9Sstevel@tonic-gate if (tohdr.Bytes_to_Bytes(bufsiz) != lim) { 396*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((1, 397*7c478bd9Sstevel@tonic-gate "Read returned a fraction of a sample frame?!\n")); 398*7c478bd9Sstevel@tonic-gate lim = bufsiz; 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate if (bufsiz > 0) { 401*7c478bd9Sstevel@tonic-gate err = to->WriteData(bptr, bufsiz, topos); 402*7c478bd9Sstevel@tonic-gate limit = topos - svto; 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate // If the write was short, back up the input pointer 405*7c478bd9Sstevel@tonic-gate if (bufsiz < lim) { 406*7c478bd9Sstevel@tonic-gate lim = bufsiz; 407*7c478bd9Sstevel@tonic-gate if (tohdr.Bytes_to_Bytes(bufsiz) != lim) { 408*7c478bd9Sstevel@tonic-gate AUDIO_DEBUG((1, 409*7c478bd9Sstevel@tonic-gate "Write returned a fraction of a sample frame?!\n")); 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate frompos = svfrom + limit; 412*7c478bd9Sstevel@tonic-gate if (!err) 413*7c478bd9Sstevel@tonic-gate err.sys = AUDIO_COPY_SHORT_OUTPUT; 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate delete bptr; 418*7c478bd9Sstevel@tonic-gate return (err); 419*7c478bd9Sstevel@tonic-gate } 420