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