1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1993-2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #include <AudioExtent.h> 28 #include <stdio.h> 29 30 // class AudioExtent methods 31 32 33 // class AudioExtent Constructor 34 AudioExtent:: 35 AudioExtent( 36 Audio* obj, // audio object to point to 37 double s, // start time 38 double e): // end time 39 Audio("[extent]"), ref(obj) 40 { 41 ref->Reference(); // reference audio object 42 SetStart(s); // set start/end times 43 SetEnd(e); 44 } 45 46 // class AudioExtent Destructor 47 AudioExtent:: 48 ~AudioExtent() 49 { 50 ref->Dereference(); // clear audio object reference 51 } 52 53 // Get referenced object 54 Audio* AudioExtent:: 55 GetRef() const 56 { 57 return (ref); 58 } 59 60 // Set referenced object 61 void AudioExtent:: 62 SetRef( 63 Audio* r) // new audio object 64 { 65 if (ref == r) // object is not changing 66 return; 67 ref->Dereference(); // dereference previous object 68 if (r != 0) { 69 ref = r; 70 ref->Reference(); // reference new object 71 } else { 72 PrintMsg(_MGET_("AudioExtent:...NULL Audio object reference"), 73 Fatal); 74 } 75 } 76 77 // Get start time 78 Double AudioExtent:: 79 GetStart() const 80 { 81 return (start); 82 } 83 84 // Set start time 85 void AudioExtent:: 86 SetStart( 87 Double s) // start time, in seconds 88 { 89 if (Undefined(s) || (s < 0.)) 90 start = 0.; 91 else 92 start = s; 93 } 94 95 // Get end time 96 Double AudioExtent:: 97 GetEnd() const 98 { 99 // If determinate endpoint, return it 100 if (!Undefined(end)) 101 return (end); 102 // Otherwise, return the endpoint of the underlying object 103 return (ref->GetLength()); 104 } 105 106 // Set end time 107 void AudioExtent:: 108 SetEnd( 109 Double e) // end time, in seconds 110 { 111 Double len; 112 113 // If known endpoint and object has known size, do not exceed size 114 if (!Undefined(e)) { 115 len = ref->GetLength(); 116 if (!Undefined(len) && (e > len)) 117 e = len; 118 } 119 end = e; 120 } 121 122 // Get the length of an audio extent 123 Double AudioExtent:: 124 GetLength() const 125 { 126 Double x; 127 128 // If extent end is indeterminate, use the end of the target object 129 x = GetEnd(); 130 // If the object length is indeterminate, then the length is 131 if (Undefined(x)) 132 return (x); 133 return (x - start); 134 } 135 136 // Construct a name for the list 137 char *AudioExtent:: 138 GetName() const 139 { 140 // XXX - construct a better name 141 return (ref->GetName()); 142 } 143 144 // Get the audio header for the current read position 145 AudioHdr AudioExtent:: 146 GetHeader() 147 { 148 return (ref->GetDHeader(ReadPosition() + start)); 149 } 150 151 // Get the audio header for the given position 152 AudioHdr AudioExtent:: 153 GetHeader( 154 Double pos) // position 155 { 156 return (ref->GetDHeader(pos + start)); 157 } 158 159 // Copy data from extent into specified buffer. 160 // No data format translation takes place. 161 // The object's read position is not updated. 162 // 163 // Since the extent could refer to a list of extents of differing encodings, 164 // clients should always use GetHeader() in combination with ReadData() 165 AudioError AudioExtent:: 166 ReadData( 167 void* buf, // destination buffer address 168 size_t& len, // buffer size (updated) 169 Double& pos) // start position (updated) 170 { 171 size_t cnt; 172 off_t buflen; 173 Double off; 174 Double newpos; 175 AudioError err; 176 177 // Save buffer size and zero transfer count 178 cnt = len; 179 len = 0; 180 181 // Position must be valid 182 if (Undefined(pos) || (pos < 0.) || ((int)cnt < 0)) 183 return (RaiseError(AUDIO_ERR_BADARG)); 184 185 // If the end is determinate, check start position and length 186 off = pos + start; 187 newpos = GetEnd(); 188 if (!Undefined(newpos)) { 189 // If starting beyond eof, give up now 190 if (off >= newpos) { 191 err = AUDIO_EOF; 192 err.sys = AUDIO_COPY_INPUT_EOF; 193 return (err); 194 } 195 196 // If the read would extend beyond end-of-extent, shorten it 197 buflen = GetHeader(pos).Time_to_Bytes((Double)(newpos - off)); 198 if (buflen == 0) { 199 err = AUDIO_EOF; 200 err.sys = AUDIO_COPY_INPUT_EOF; 201 return (err); 202 } 203 if (buflen < cnt) 204 cnt = (size_t)buflen; 205 } 206 // Zero-length reads are easy 207 if (cnt == 0) { 208 err = AUDIO_SUCCESS; 209 err.sys = AUDIO_COPY_ZERO_LIMIT; 210 return (err); 211 } 212 213 // Save the offset, read data, and update the returned position 214 newpos = off; 215 len = cnt; 216 err = ref->ReadData(buf, len, newpos); 217 pos = (newpos - start); // XXX - calculate bytes and convert? 218 return (err); 219 } 220 221 // Write to AudioExtent is (currently) prohibited 222 AudioError AudioExtent:: 223 WriteData( 224 void*, // destination buffer address 225 size_t& len, // buffer size (updated) 226 Double&) // start position (updated) 227 { 228 len = 0; 229 return (RaiseError(AUDIO_ERR_NOEFFECT)); 230 } 231