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