8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / audio / utilities / AudioList.cc
blob624c4fc414b6e11e0fc4702a80d93dd9d7e66e3b
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1993-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <AudioExtent.h>
30 #include <AudioList.h>
31 #include <AudioDebug.h>
33 // class AudioList methods
36 // class AudioListEntry Constructor
37 AudioList::AudioListEntry::
38 AudioListEntry(
39 Audio* obj): // audio object to point to
40 aptr(0), next(0), prev(0)
42 // A NULL object is only valid in dummy entries, such as list heads
43 newptr(obj);
46 // class AudioListEntry Destructor
47 AudioList::AudioListEntry::
48 ~AudioListEntry()
50 newptr(0);
51 if (next != 0) {
52 next->prev = prev;
54 if (prev != 0) {
55 prev->next = next;
59 // Set a new extent pointer in an AudioListEntry
60 void AudioList::AudioListEntry::
61 newptr(
62 Audio* newa) // new object
64 if (aptr != 0)
65 aptr->Dereference();
66 aptr = newa;
67 if (aptr != 0)
68 aptr->Reference();
71 // Link object into list
72 // Link in a new AudioListEntry
73 void AudioList::AudioListEntry::
74 link(
75 AudioListEntry* after) // link after this one
77 // Link object into list
78 prev = after;
79 next = after->next;
80 after->next = this;
81 if (next != 0)
82 next->prev = this;
85 // Split an AudioListEntry at the specified offset
86 void AudioList::AudioListEntry::
87 split(
88 Double pos) // split offset
90 AudioExtent* e1;
91 AudioExtent* e2;
92 AudioListEntry* newp;
94 // Create two extents referencing this object
95 e1 = new AudioExtent(aptr, 0., pos);
96 e2 = new AudioExtent(aptr, pos, AUDIO_UNKNOWN_TIME);
98 // Set the current entry to the first extent and append the second
99 newptr(e1);
100 newp = new AudioListEntry(e2);
101 newp->link(this);
105 // class AudioList Constructor
106 AudioList::
107 AudioList(
108 const char *local_name): // name string
109 Audio(local_name), head(0)
113 // class AudioList Destructor
114 AudioList::
115 ~AudioList()
117 // Delete all entries in the list
118 while (first() != 0)
119 delete first();
122 // Get the first entry in the list
123 AudioList::AudioListEntry* AudioList::
124 first() const
126 return (head.next);
129 // Get the extent and offset corresponding to a given position
130 // Return FALSE if no extents in list or position is beyond eof
131 Boolean AudioList::
132 getposition(
133 Double& pos, // target position (updated)
134 AudioListEntry*& ep) const // returned extent pointer
136 Double length;
138 // Position must be specified
139 if (Undefined(pos))
140 return (FALSE);
142 // Get the first extent in the list
143 ep = first();
144 while (ep != 0) {
145 // Get length of extent
146 length = ep->aptr->GetLength();
147 if (Undefined(length)) {
148 // Can't determine sizes beyond this
149 return (TRUE);
151 // If the remaining offset is inside the current extent
152 if (length > pos)
153 return (TRUE);
155 // Move on to the next extent
156 pos -= length;
157 ep = ep->next;
159 return (FALSE);
162 // Get the total length of the audio list
163 Double AudioList::
164 GetLength() const
166 AudioListEntry* ep;
167 Double sum;
168 Double x;
170 for (sum = 0., ep = first(); ep != 0; ep = ep->next) {
171 // Accumulate times for each extent
172 // Indeterminate extents screw up the calculation
173 x = ep->aptr->GetLength();
174 if (Undefined(x))
175 return (x);
176 sum += x;
178 return (sum);
181 // Construct a name for the list
182 char *AudioList::
183 GetName() const
185 // XXX - construct a better name
186 return (Audio::GetName());
189 // Get the audio header for the current read position
190 AudioHdr AudioList::
191 GetHeader()
193 return (GetHeader(ReadPosition()));
196 // Get the audio header for the given position
197 AudioHdr AudioList::
198 GetHeader(
199 Double pos) // position
201 AudioListEntry* ep;
203 // Get the extent pointer for the given position
204 if (!getposition(pos, ep)) {
205 AudioHdr h;
207 if (pos != 0.) {
208 PrintMsg(_MGET_(
209 "AudioHdr:GetHeader()...position is beyond eof"),
210 Warning);
211 return (h);
213 if ((ep = first()) != 0)
214 return (ep->aptr->GetHeader());
215 return (h);
217 // Get the header for the proper offset in the extent
218 return (ep->aptr->GetDHeader(pos));
221 // Copy data from list into specified buffer.
222 // No data format translation takes place.
223 // The object's read position is not updated.
225 // Since list could contain extents of differing encodings,
226 // clients should always use GetHeader() in combination with ReadData()
227 AudioError AudioList::
228 ReadData(
229 void* buf, // destination buffer address
230 size_t& len, // buffer size (updated)
231 Double& pos) // start position (updated)
233 AudioListEntry* ep;
234 size_t cnt;
235 Double off;
236 Double newpos;
237 AudioError err;
239 // Save buffer size
240 cnt = len;
242 // Position must be valid
243 if (Undefined(pos) || (pos < 0.) || ((int)cnt < 0))
244 return (RaiseError(AUDIO_ERR_BADARG));
246 // Loop until data is returned or error
247 // XXX - THIS IS WRONG! THE HEADER COULD CHANGE!
248 do {
249 // Get the extent/offset for read position; clear return count
250 len = 0;
251 off = pos;
252 if (!getposition(off, ep)) {
253 err = AUDIO_EOF;
254 err.sys = AUDIO_COPY_INPUT_EOF;
255 return (err);
258 // Save the offset and read some data
259 newpos = off;
260 len = cnt;
261 err = ep->aptr->ReadData(buf, len, newpos);
263 // If no eof on this list entry, or no more data, we're done
264 if ((err != AUDIO_EOF) || (err.sys != AUDIO_COPY_INPUT_EOF) ||
265 (ep->next == 0)) {
266 break;
269 // Advance to next list entry
270 // XXX - Is this problemmatic, too?
271 pos += ep->aptr->GetLength() - off;
272 } while (TRUE);
274 // Update the byte count and position
275 pos += (newpos - off); // XXX - recalculate?
276 return (err);
279 // Write to AudioList is (currently) prohibited
280 AudioError AudioList::
281 WriteData(
282 void*, // destination buffer address
283 size_t& len, // buffer size (updated)
284 Double&) // start position (updated)
286 len = 0;
287 return (RaiseError(AUDIO_ERR_NOEFFECT));
290 // Insert an entry at the start
291 AudioError AudioList::
292 Insert(
293 Audio* obj) // object to insert
295 Double pos; // insertion offset, in seconds
297 return (Insert(obj, pos = 0.));
300 // Insert an entry at a specified position
301 AudioError AudioList::
302 Insert(
303 Audio* obj, // object to insert
304 Double pos) // insertion offset, in seconds
306 AudioListEntry *ep;
307 AudioListEntry *prev;
309 // Find the insertion point
310 if (first() == 0) {
311 prev = &head; // this is the first extent
312 } else {
313 if (!getposition(pos, prev)) {
314 if (pos == 0.) {
315 // Append extent to end of list
316 return (Append(obj));
317 } else {
318 return (RaiseError(AUDIO_ERR_BADARG));
320 } else if (pos != 0.) {
321 // The insertion is in an extent, split it in two
322 prev->split(pos);
323 } else {
324 // Insert before the current position
325 prev = prev->prev;
328 // Create object and link into list
329 ep = new AudioListEntry(obj);
330 ep->link(prev);
332 return (AUDIO_SUCCESS);
335 // Append an entry to a list
336 AudioError AudioList::
337 Append(
338 Audio* obj) // object to append
340 AudioListEntry *ep;
341 AudioListEntry *prev;
343 // Find the last extent in the list
344 for (prev = &head; prev->next != 0; prev = prev->next)
345 continue;
347 // Create object and link into list
348 ep = new AudioListEntry(obj);
349 ep->link(prev);
350 return (AUDIO_SUCCESS);
353 // Copy routine for lists
354 AudioError AudioList::
355 AsyncCopy(
356 Audio* to, // audio object to copy to
357 Double& frompos, // input pos (updated)
358 Double& topos, // output pos (updated)
359 Double& limit) // amt to copy (updated)
361 AudioListEntry* ep;
362 Double svlim;
363 Double newpos;
364 Double off;
365 AudioError err;
367 svlim = limit;
368 // Loop until data is returned or error
369 // XXX - THIS IS WRONG! THE HEADER COULD CHANGE!
370 do {
371 // Get the extent and offset for the read position
372 off = frompos;
373 if (!getposition(off, ep)) {
374 // nothing written, limit should reflect this
375 limit = 0.0;
376 err = AUDIO_EOF;
377 err.sys = AUDIO_COPY_INPUT_EOF;
378 return (err);
381 // Save the offset and do a copy
382 newpos = off;
383 limit = svlim;
384 err = ep->aptr->AsyncCopy(to, newpos, topos, limit);
386 // If no eof on this list entry, or no more data, we're done
387 if ((err != AUDIO_EOF) || (err.sys != AUDIO_COPY_INPUT_EOF) ||
388 (ep->next == 0)) {
389 break;
392 // Advance to next list entry
393 // XXX - Is this problemmatic, too?
394 frompos += ep->aptr->GetLength() - off;
395 } while (TRUE);
397 // Update the byte count and position
398 frompos += (newpos - off); // XXX - recalculate?
399 return (err);