xref: /illumos-gate/usr/src/cmd/audio/utilities/AudioExtent.cc (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <AudioExtent.h>
30 #include <stdio.h>
31 
32 // class AudioExtent methods
33 
34 
35 // class AudioExtent Constructor
36 AudioExtent::
37 AudioExtent(
38 	Audio*		obj,		// audio object to point to
39 	double		s,		// start time
40 	double		e):		// end time
41 	Audio("[extent]"), ref(obj)
42 {
43 	ref->Reference();		// reference audio object
44 	SetStart(s);			// set start/end times
45 	SetEnd(e);
46 }
47 
48 // class AudioExtent Destructor
49 AudioExtent::
50 ~AudioExtent()
51 {
52 	ref->Dereference();		// clear audio object reference
53 }
54 
55 // Get referenced object
56 Audio* AudioExtent::
57 GetRef() const
58 {
59 	return (ref);
60 }
61 
62 // Set referenced object
63 void AudioExtent::
64 SetRef(
65 	Audio*		r)		// new audio object
66 {
67 	if (ref == r)			// object is not changing
68 		return;
69 	ref->Dereference();		// dereference previous object
70 	if (r != 0) {
71 		ref = r;
72 		ref->Reference();	// reference new object
73 	} else {
74 		PrintMsg(_MGET_("AudioExtent:...NULL Audio object reference"),
75 		    Fatal);
76 	}
77 }
78 
79 // Get start time
80 Double AudioExtent::
81 GetStart() const
82 {
83 	return (start);
84 }
85 
86 // Set start time
87 void AudioExtent::
88 SetStart(
89 	Double		s)		// start time, in seconds
90 {
91 	if (Undefined(s) || (s < 0.))
92 		start = 0.;
93 	else
94 		start = s;
95 }
96 
97 // Get end time
98 Double AudioExtent::
99 GetEnd() const
100 {
101 	// If determinate endpoint, return it
102 	if (!Undefined(end))
103 		return (end);
104 	// Otherwise, return the endpoint of the underlying object
105 	return (ref->GetLength());
106 }
107 
108 // Set end time
109 void AudioExtent::
110 SetEnd(
111 	Double		e)		// end time, in seconds
112 {
113 	Double		len;
114 
115 	// If known endpoint and object has known size, do not exceed size
116 	if (!Undefined(e)) {
117 		len = ref->GetLength();
118 		if (!Undefined(len) && (e > len))
119 			e = len;
120 	}
121 	end = e;
122 }
123 
124 // Get the length of an audio extent
125 Double AudioExtent::
126 GetLength() const
127 {
128 	Double		x;
129 
130 	// If extent end is indeterminate, use the end of the target object
131 	x = GetEnd();
132 	// If the object length is indeterminate, then the length is
133 	if (Undefined(x))
134 		return (x);
135 	return (x - start);
136 }
137 
138 // Construct a name for the list
139 char *AudioExtent::
140 GetName() const
141 {
142 	// XXX - construct a better name
143 	return (ref->GetName());
144 }
145 
146 // Get the audio header for the current read position
147 AudioHdr AudioExtent::
148 GetHeader()
149 {
150 	return (ref->GetDHeader(ReadPosition() + start));
151 }
152 
153 // Get the audio header for the given position
154 AudioHdr AudioExtent::
155 GetHeader(
156 	Double		pos)		// position
157 {
158 	return (ref->GetDHeader(pos + start));
159 }
160 
161 // Copy data from extent into specified buffer.
162 // No data format translation takes place.
163 // The object's read position is not updated.
164 //
165 // Since the extent could refer to a list of extents of differing encodings,
166 // clients should always use GetHeader() in combination with ReadData()
167 AudioError AudioExtent::
168 ReadData(
169 	void*		buf,		// destination buffer address
170 	size_t&		len,		// buffer size (updated)
171 	Double&		pos)		// start position (updated)
172 {
173 	size_t		cnt;
174 	off_t		buflen;
175 	Double		off;
176 	Double		newpos;
177 	AudioError	err;
178 
179 	// Save buffer size and zero transfer count
180 	cnt = len;
181 	len = 0;
182 
183 	// Position must be valid
184 	if (Undefined(pos) || (pos < 0.) || ((int)cnt < 0))
185 		return (RaiseError(AUDIO_ERR_BADARG));
186 
187 	// If the end is determinate, check start position and length
188 	off = pos + start;
189 	newpos = GetEnd();
190 	if (!Undefined(newpos)) {
191 		// If starting beyond eof, give up now
192 		if (off >= newpos) {
193 			err = AUDIO_EOF;
194 			err.sys = AUDIO_COPY_INPUT_EOF;
195 			return (err);
196 		}
197 
198 		// If the read would extend beyond end-of-extent, shorten it
199 		buflen = GetHeader(pos).Time_to_Bytes((Double)(newpos - off));
200 		if (buflen == 0) {
201 			err = AUDIO_EOF;
202 			err.sys = AUDIO_COPY_INPUT_EOF;
203 			return (err);
204 		}
205 		if (buflen < cnt)
206 			cnt = (size_t)buflen;
207 	}
208 	// Zero-length reads are easy
209 	if (cnt == 0) {
210 		err = AUDIO_SUCCESS;
211 		err.sys = AUDIO_COPY_ZERO_LIMIT;
212 		return (err);
213 	}
214 
215 	// Save the offset, read data, and update the returned position
216 	newpos = off;
217 	len = cnt;
218 	err = ref->ReadData(buf, len, newpos);
219 	pos = (newpos - start);		// XXX - calculate bytes and convert?
220 	return (err);
221 }
222 
223 // Write to AudioExtent is (currently) prohibited
224 AudioError AudioExtent::
225 WriteData(
226 	void*,				// destination buffer address
227 	size_t&		len,		// buffer size (updated)
228 	Double&)			// start position (updated)
229 {
230 	len = 0;
231 	return (RaiseError(AUDIO_ERR_NOEFFECT));
232 }
233