xref: /haiku/src/kits/game/PushGameSound.cpp (revision effe53fae93cf526f5a978ba578b0f07879d9f24)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		GameSound.cpp
23 //	Author:			Christopher ML Zumwalt May (zummy@users.sf.net)
24 //	Description:	BPushGameSound class
25 //------------------------------------------------------------------------------
26 
27 #include <string.h>
28 
29 #include <List.h>
30 #include <PushGameSound.h>
31 
32 #include "GSUtility.h"
33 
34 
35 BPushGameSound::BPushGameSound(size_t inBufferFrameCount, const gs_audio_format *format,
36 			size_t inBufferCount, BGameSoundDevice *device)
37  	:	BStreamingGameSound(inBufferFrameCount, format, inBufferCount, device)
38 {
39 	if (InitCheck() != B_OK)
40 		return;
41 
42 	status_t error = SetParameters(inBufferFrameCount, format, inBufferCount);
43 	if (error == B_OK)
44 		fPageLocked = new BList;
45 	else
46 		SetInitError(error);
47 }
48 
49 
50 BPushGameSound::BPushGameSound(BGameSoundDevice * device)
51 		:	BStreamingGameSound(device),
52 			fLockPos(0),
53 			fPlayPos(0),
54 			fBuffer(NULL),
55 			fPageSize(0),
56 			fPageCount(0),
57 			fBufferSize(0)
58 {
59 	fPageLocked = new BList;
60 }
61 
62 BPushGameSound::~BPushGameSound()
63 {
64 	delete [] fBuffer;
65 	delete fPageLocked;
66 }
67 
68 
69 BPushGameSound::lock_status
70 BPushGameSound::LockNextPage(void **out_pagePtr, size_t *out_pageSize)
71 {
72 	// the user can not lock every page
73 	if (fPageLocked->CountItems() > fPageCount - 3)
74 		return lock_failed;
75 
76 	// the user cann't lock a page being played
77 	if (fLockPos < fPlayPos
78 		&& fLockPos + fPageSize > fPlayPos)
79 		return lock_failed;
80 
81 	// lock the page
82 	char * lockPage = &fBuffer[fLockPos];
83 	fPageLocked->AddItem(lockPage);
84 
85 	// move the locker to the next page
86 	fLockPos += fPageSize;
87 	if (fLockPos > fBufferSize)
88 		fLockPos = 0;
89 
90 	*out_pagePtr = lockPage;
91 	*out_pageSize = fPageSize;
92 
93 	return lock_ok;
94 }
95 
96 
97 status_t
98 BPushGameSound::UnlockPage(void *in_pagePtr)
99 {
100 	return (fPageLocked->RemoveItem(in_pagePtr)) ? B_OK : B_ERROR;
101 }
102 
103 
104 BPushGameSound::lock_status
105 BPushGameSound::LockForCyclic(void **out_basePtr, size_t *out_size)
106 {
107 	*out_basePtr = fBuffer;
108 	*out_size = fBufferSize;
109 	return lock_ok;
110 }
111 
112 
113 status_t
114 BPushGameSound::UnlockCyclic()
115 {
116 	return B_OK;
117 }
118 
119 
120 size_t
121 BPushGameSound::CurrentPosition()
122 {
123 	return fPlayPos;
124 }
125 
126 
127 BGameSound *
128 BPushGameSound::Clone() const
129 {
130 	gs_audio_format format = Format();
131 	size_t frameSize = get_sample_size(format.format) * format.channel_count;
132 	size_t bufferFrameCount = fPageSize / frameSize;
133 
134 	return new BPushGameSound(bufferFrameCount, &format, fPageCount, Device());
135 }
136 
137 
138 status_t
139 BPushGameSound::Perform(int32 selector, void *data)
140 {
141 	return B_ERROR;
142 }
143 
144 
145 status_t
146 BPushGameSound::SetParameters(size_t inBufferFrameCount,
147 							  const gs_audio_format *format,
148 							  size_t inBufferCount)
149 {
150 	status_t error = BStreamingGameSound::SetParameters(inBufferFrameCount, format, inBufferCount);
151 	if (error != B_OK)
152 		return error;
153 
154 	size_t frameSize = get_sample_size(format->format) * format->channel_count;
155 
156 	fPageCount = inBufferCount;
157 	fPageSize = frameSize * inBufferFrameCount;
158 	fBufferSize = fPageSize * fPageCount;
159 
160 	fBuffer = new char[fBufferSize];
161 
162 	return B_OK;
163 }
164 
165 
166 status_t
167 BPushGameSound::SetStreamHook(void (*hook)(void * inCookie, void * inBuffer, size_t inByteCount, BStreamingGameSound * me),
168 							  void * cookie)
169 {
170 	return B_ERROR;
171 }
172 
173 
174 void
175 BPushGameSound::FillBuffer(void *inBuffer, size_t inByteCount)
176 {
177 	size_t bytes = inByteCount;
178 
179 	if (!BytesReady(&bytes))
180 		return;
181 
182 	if (fPlayPos + bytes > fBufferSize) {
183 		size_t remainder = fPlayPos + bytes - fBufferSize;
184 		char * buffer = (char*)inBuffer;
185 
186 		// fill the buffer with the samples left at the end of our buffer
187 		memcpy(buffer, &fBuffer[fPlayPos], remainder);
188 		fPlayPos = 0;
189 
190 		// fill the remainder of the buffer by looping to the start
191 		// of the buffer if it isn't locked
192 		bytes -= remainder;
193 		if (BytesReady(&bytes)) {
194 			memcpy(&buffer[remainder], fBuffer, bytes);
195 			fPlayPos += bytes;
196 		}
197 	} else {
198 		memcpy(inBuffer, &fBuffer[fPlayPos], bytes);
199 		fPlayPos += bytes;
200 	}
201 
202 	BStreamingGameSound::FillBuffer(inBuffer, inByteCount);
203 }
204 
205 
206 bool
207 BPushGameSound::BytesReady(size_t * bytes)
208 {
209 	if (fPageLocked->CountItems() <= 0)
210 		return true;
211 
212 	size_t start = fPlayPos;
213 	size_t ready = fPlayPos;
214 	int32 page = int32(start / fPageSize);
215 
216 	// return if there is nothing to do
217 	if (fPageLocked->HasItem(&fBuffer[page * fPageSize]))
218 		return false;
219 
220 	while (ready < *bytes) {
221 		ready += fPageSize;
222 		page = int32(ready / fPageSize);
223 
224 		if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) {
225 			// we have found a locked page
226 			*bytes = ready - start - (ready - page * fPageSize);
227 			return true;
228 		}
229 	}
230 
231 	// all of the bytes are ready
232 	return true;
233 }
234 
235 /* unimplemented for protection of the user:
236  *
237  * BPushGameSound::BPushGameSound()
238  * BPushGameSound::BPushGameSound(const BPushGameSound &)
239  * BPushGameSound &BPushGameSound::operator=(const BPushGameSound &)
240  */
241 
242 
243 status_t
244 BPushGameSound::_Reserved_BPushGameSound_0(int32 arg, ...)
245 {
246 	return B_ERROR;
247 }
248 
249 
250 status_t
251 BPushGameSound::_Reserved_BPushGameSound_1(int32 arg, ...)
252 {
253 	return B_ERROR;
254 }
255 
256 
257 status_t
258 BPushGameSound::_Reserved_BPushGameSound_2(int32 arg, ...)
259 {
260 	return B_ERROR;
261 }
262 
263 
264 status_t
265 BPushGameSound::_Reserved_BPushGameSound_3(int32 arg, ...)
266 {
267 	return B_ERROR;
268 }
269 
270 
271 status_t
272 BPushGameSound::_Reserved_BPushGameSound_4(int32 arg, ...)
273 {
274 	return B_ERROR;
275 }
276 
277 
278 status_t
279 BPushGameSound::_Reserved_BPushGameSound_5(int32 arg, ...)
280 {
281 	return B_ERROR;
282 }
283 
284 
285 status_t
286 BPushGameSound::_Reserved_BPushGameSound_6(int32 arg, ...)
287 {
288 	return B_ERROR;
289 }
290 
291 
292 status_t
293 BPushGameSound::_Reserved_BPushGameSound_7(int32 arg, ...)
294 {
295 	return B_ERROR;
296 }
297 
298 
299 status_t
300 BPushGameSound::_Reserved_BPushGameSound_8(int32 arg, ...)
301 {
302 	return B_ERROR;
303 }
304 
305 
306 status_t
307 BPushGameSound::_Reserved_BPushGameSound_9(int32 arg, ...)
308 {
309 	return B_ERROR;
310 }
311 
312 
313 status_t
314 BPushGameSound::_Reserved_BPushGameSound_10(int32 arg, ...)
315 {
316 	return B_ERROR;
317 }
318 
319 
320 status_t
321 BPushGameSound::_Reserved_BPushGameSound_11(int32 arg, ...)
322 {
323 	return B_ERROR;
324 }
325 
326 
327 status_t
328 BPushGameSound::_Reserved_BPushGameSound_12(int32 arg, ...)
329 {
330 	return B_ERROR;
331 }
332 
333 
334 status_t
335 BPushGameSound::_Reserved_BPushGameSound_13(int32 arg, ...)
336 {
337 	return B_ERROR;
338 }
339 
340 
341 status_t
342 BPushGameSound::_Reserved_BPushGameSound_14(int32 arg, ...)
343 {
344 	return B_ERROR;
345 }
346 
347 
348 status_t
349 BPushGameSound::_Reserved_BPushGameSound_15(int32 arg, ...)
350 {
351 	return B_ERROR;
352 }
353 
354 
355 status_t
356 BPushGameSound::_Reserved_BPushGameSound_16(int32 arg, ...)
357 {
358 	return B_ERROR;
359 }
360 
361 
362 status_t
363 BPushGameSound::_Reserved_BPushGameSound_17(int32 arg, ...)
364 {
365 	return B_ERROR;
366 }
367 
368 
369 status_t
370 BPushGameSound::_Reserved_BPushGameSound_18(int32 arg, ...)
371 {
372 	return B_ERROR;
373 }
374 
375 
376 status_t
377 BPushGameSound::_Reserved_BPushGameSound_19(int32 arg, ...)
378 {
379 	return B_ERROR;
380 }
381 
382 
383 status_t
384 BPushGameSound::_Reserved_BPushGameSound_20(int32 arg, ...)
385 {
386 	return B_ERROR;
387 }
388 
389 
390 status_t
391 BPushGameSound::_Reserved_BPushGameSound_21(int32 arg, ...)
392 {
393 	return B_ERROR;
394 }
395 
396 
397 status_t
398 BPushGameSound::_Reserved_BPushGameSound_22(int32 arg, ...)
399 {
400 	return B_ERROR;
401 }
402 
403 
404 status_t
405 BPushGameSound::_Reserved_BPushGameSound_23(int32 arg, ...)
406 {
407 	return B_ERROR;
408 }
409 
410 
411