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::
AudioExtent(Audio * obj,double s,double e)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::
~AudioExtent()48 ~AudioExtent()
49 {
50 ref->Dereference(); // clear audio object reference
51 }
52
53 // Get referenced object
54 Audio* AudioExtent::
GetRef() const55 GetRef() const
56 {
57 return (ref);
58 }
59
60 // Set referenced object
61 void AudioExtent::
SetRef(Audio * r)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::
GetStart() const79 GetStart() const
80 {
81 return (start);
82 }
83
84 // Set start time
85 void AudioExtent::
SetStart(Double s)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::
GetEnd() const97 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::
SetEnd(Double e)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::
GetLength() const124 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::
GetName() const138 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::
GetHeader()146 GetHeader()
147 {
148 return (ref->GetDHeader(ReadPosition() + start));
149 }
150
151 // Get the audio header for the given position
152 AudioHdr AudioExtent::
GetHeader(Double pos)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::
ReadData(void * buf,size_t & len,Double & pos)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::
WriteData(void *,size_t & len,Double &)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