xref: /haiku/src/kits/game/PushGameSound.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
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 // Standard Includes -----------------------------------------------------------
28 #include <string.h>
29 
30 // System Includes -------------------------------------------------------------
31 #include <List.h>
32 
33 // Project Includes ------------------------------------------------------------
34 #include <GSUtility.h>
35 
36 // Local Includes --------------------------------------------------------------
37 #include <PushGameSound.h>
38 
39 // Local Defines ---------------------------------------------------------------
40 
41 // BPushGameSound --------------------------------------------------------------
42 BPushGameSound::BPushGameSound(size_t inBufferFrameCount,
43 							   const gs_audio_format *format,
44 							   size_t inBufferCount,
45 							   BGameSoundDevice *device)
46  	:	BStreamingGameSound(inBufferFrameCount, format, inBufferCount, device)
47 {
48 	if (InitCheck() == B_OK)
49 	{
50 		status_t error = SetParameters(inBufferFrameCount, format, inBufferCount);
51 		if (error != B_OK)
52 			fPageLocked = new BList;
53 		else
54 			SetInitError(error);
55 	}
56 }
57 
58 
59 BPushGameSound::BPushGameSound(BGameSoundDevice * device)
60 		:	BStreamingGameSound(device),
61 			fLockPos(0),
62 			fPlayPos(0),
63 			fBuffer(NULL),
64 			fPageSize(0),
65 			fPageCount(0),
66 			fBufferSize(0)
67 {
68 	fPageLocked = new BList;
69 }
70 
71 BPushGameSound::~BPushGameSound()
72 {
73 	delete [] fBuffer;
74 	delete fPageLocked;
75 }
76 
77 
78 BPushGameSound::lock_status
79 BPushGameSound::LockNextPage(void **out_pagePtr,
80 							 size_t *out_pageSize)
81 {
82 	// the user can not lock every page
83 	if (fPageLocked->CountItems() > fPageCount - 3) return lock_failed;
84 
85 	// the user cann't lock a page being played
86 	if (fLockPos < fPlayPos && fLockPos + fPageSize > fPlayPos) return lock_failed;
87 
88 	// lock the page
89 	char * lockPage = &fBuffer[fLockPos];
90 	fPageLocked->AddItem(lockPage);
91 
92 	// move the locker to the next page
93 	fLockPos += fPageSize;
94 	if (fLockPos > fBufferSize) fLockPos = 0;
95 
96 	*out_pagePtr = lockPage;
97 	*out_pageSize = fPageSize;
98 
99 	return lock_ok;
100 }
101 
102 
103 status_t
104 BPushGameSound::UnlockPage(void *in_pagePtr)
105 {
106 	return (fPageLocked->RemoveItem(in_pagePtr)) ? B_OK : B_ERROR;
107 }
108 
109 
110 BPushGameSound::lock_status
111 BPushGameSound::LockForCyclic(void **out_basePtr,
112 							  size_t *out_size)
113 {
114 	*out_basePtr = fBuffer;
115 	*out_size = fBufferSize;
116 	return lock_ok;
117 }
118 
119 
120 status_t
121 BPushGameSound::UnlockCyclic()
122 {
123 	return B_OK;
124 }
125 
126 
127 size_t
128 BPushGameSound::CurrentPosition()
129 {
130 	return fPlayPos;
131 }
132 
133 
134 BGameSound *
135 BPushGameSound::Clone() const
136 {
137 	gs_audio_format format = Format();
138 	size_t frameSize = get_sample_size(format.format) * format.channel_count;
139 	size_t bufferFrameCount = fPageSize / frameSize;
140 
141 	return new BPushGameSound(bufferFrameCount, &format, fPageCount, Device());
142 }
143 
144 
145 status_t
146 BPushGameSound::Perform(int32 selector,
147 						void *data)
148 {
149 	return B_ERROR;
150 }
151 
152 
153 status_t
154 BPushGameSound::SetParameters(size_t inBufferFrameCount,
155 							  const gs_audio_format *format,
156 							  size_t inBufferCount)
157 {
158 	status_t error = BStreamingGameSound::SetParameters(inBufferFrameCount, format, inBufferCount);
159 	if (error != B_OK) return error;
160 
161 	size_t frameSize = get_sample_size(format->format) * format->channel_count;
162 
163 	fPageCount = inBufferCount;
164 	fPageSize = frameSize * inBufferFrameCount;
165 	fBufferSize = fPageSize * fPageCount;
166 
167 	fBuffer = new char[fBufferSize];
168 
169 	return B_OK;
170 }
171 
172 
173 status_t
174 BPushGameSound::SetStreamHook(void (*hook)(void * inCookie, void * inBuffer, size_t inByteCount, BStreamingGameSound * me),
175 							  void * cookie)
176 {
177 	return B_ERROR;
178 }
179 
180 
181 void
182 BPushGameSound::FillBuffer(void *inBuffer,
183 						   size_t inByteCount)
184 {
185 	size_t bytes = inByteCount;
186 
187 	if (BytesReady(&bytes))
188 	{
189 		if (fPlayPos + bytes > fBufferSize)
190 		{
191 			size_t remainder = fPlayPos + bytes - fBufferSize;
192 			char * buffer = (char*)inBuffer;
193 
194 			// fill the buffer with the samples left at the end of our buffer
195 			memcpy(buffer, &fBuffer[fPlayPos], remainder);
196 			fPlayPos = 0;
197 
198 			// fill the remainder of the buffer by looping to the start
199 			// of the buffer if it isn't locked
200 			bytes -= remainder;
201 			if (BytesReady(&bytes))
202 			{
203 				memcpy(&buffer[remainder], fBuffer, bytes);
204 				fPlayPos += bytes;
205 			}
206 		}
207 		else
208 		{
209 			memcpy(inBuffer, &fBuffer[fPlayPos], bytes);
210 			fPlayPos += bytes;
211 		}
212 
213 		BStreamingGameSound::FillBuffer(inBuffer, inByteCount);
214 	}
215 }
216 
217 
218 bool
219 BPushGameSound::BytesReady(size_t * bytes)
220 {
221 	if (fPageLocked->CountItems() > 0)
222 	{
223 		size_t start = fPlayPos;
224 		size_t ready = fPlayPos;
225 		int32 page = int32(start / fPageSize);
226 
227 		// return if there is nothing to do
228 		if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) return false;
229 
230 		while (ready < *bytes)
231 		{
232 			ready += fPageSize;
233 			page = int32(ready / fPageSize);
234 
235 			if (fPageLocked->HasItem(&fBuffer[page * fPageSize]))
236 			{
237 				// we have found a locked page
238 				*bytes = ready - start - (ready - page * fPageSize);
239 				return true;
240 			}
241 		}
242 	}
243 
244 	// all of the bytes are ready
245 	return true;
246 }
247 
248 /* unimplemented for protection of the user:
249  *
250  * BPushGameSound::BPushGameSound()
251  * BPushGameSound::BPushGameSound(const BPushGameSound &)
252  * BPushGameSound &BPushGameSound::operator=(const BPushGameSound &)
253  */
254 
255 
256 status_t
257 BPushGameSound::_Reserved_BPushGameSound_0(int32 arg, ...)
258 {
259 	return B_ERROR;
260 }
261 
262 
263 status_t
264 BPushGameSound::_Reserved_BPushGameSound_1(int32 arg, ...)
265 {
266 	return B_ERROR;
267 }
268 
269 
270 status_t
271 BPushGameSound::_Reserved_BPushGameSound_2(int32 arg, ...)
272 {
273 	return B_ERROR;
274 }
275 
276 
277 status_t
278 BPushGameSound::_Reserved_BPushGameSound_3(int32 arg, ...)
279 {
280 	return B_ERROR;
281 }
282 
283 
284 status_t
285 BPushGameSound::_Reserved_BPushGameSound_4(int32 arg, ...)
286 {
287 	return B_ERROR;
288 }
289 
290 
291 status_t
292 BPushGameSound::_Reserved_BPushGameSound_5(int32 arg, ...)
293 {
294 	return B_ERROR;
295 }
296 
297 
298 status_t
299 BPushGameSound::_Reserved_BPushGameSound_6(int32 arg, ...)
300 {
301 	return B_ERROR;
302 }
303 
304 
305 status_t
306 BPushGameSound::_Reserved_BPushGameSound_7(int32 arg, ...)
307 {
308 	return B_ERROR;
309 }
310 
311 
312 status_t
313 BPushGameSound::_Reserved_BPushGameSound_8(int32 arg, ...)
314 {
315 	return B_ERROR;
316 }
317 
318 
319 status_t
320 BPushGameSound::_Reserved_BPushGameSound_9(int32 arg, ...)
321 {
322 	return B_ERROR;
323 }
324 
325 
326 status_t
327 BPushGameSound::_Reserved_BPushGameSound_10(int32 arg, ...)
328 {
329 	return B_ERROR;
330 }
331 
332 
333 status_t
334 BPushGameSound::_Reserved_BPushGameSound_11(int32 arg, ...)
335 {
336 	return B_ERROR;
337 }
338 
339 
340 status_t
341 BPushGameSound::_Reserved_BPushGameSound_12(int32 arg, ...)
342 {
343 	return B_ERROR;
344 }
345 
346 
347 status_t
348 BPushGameSound::_Reserved_BPushGameSound_13(int32 arg, ...)
349 {
350 	return B_ERROR;
351 }
352 
353 
354 status_t
355 BPushGameSound::_Reserved_BPushGameSound_14(int32 arg, ...)
356 {
357 	return B_ERROR;
358 }
359 
360 
361 status_t
362 BPushGameSound::_Reserved_BPushGameSound_15(int32 arg, ...)
363 {
364 	return B_ERROR;
365 }
366 
367 
368 status_t
369 BPushGameSound::_Reserved_BPushGameSound_16(int32 arg, ...)
370 {
371 	return B_ERROR;
372 }
373 
374 
375 status_t
376 BPushGameSound::_Reserved_BPushGameSound_17(int32 arg, ...)
377 {
378 	return B_ERROR;
379 }
380 
381 
382 status_t
383 BPushGameSound::_Reserved_BPushGameSound_18(int32 arg, ...)
384 {
385 	return B_ERROR;
386 }
387 
388 
389 status_t
390 BPushGameSound::_Reserved_BPushGameSound_19(int32 arg, ...)
391 {
392 	return B_ERROR;
393 }
394 
395 
396 status_t
397 BPushGameSound::_Reserved_BPushGameSound_20(int32 arg, ...)
398 {
399 	return B_ERROR;
400 }
401 
402 
403 status_t
404 BPushGameSound::_Reserved_BPushGameSound_21(int32 arg, ...)
405 {
406 	return B_ERROR;
407 }
408 
409 
410 status_t
411 BPushGameSound::_Reserved_BPushGameSound_22(int32 arg, ...)
412 {
413 	return B_ERROR;
414 }
415 
416 
417 status_t
418 BPushGameSound::_Reserved_BPushGameSound_23(int32 arg, ...)
419 {
420 	return B_ERROR;
421 }
422 
423 
424