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