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