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