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, 19 const gs_audio_format *format, size_t inBufferCount, 20 BGameSoundDevice *device) 21 : 22 BStreamingGameSound(inBufferFrameCount, format, inBufferCount, device), 23 fLockPos(0), 24 fPlayPos(0) 25 { 26 fPageLocked = new BList; 27 28 size_t frameSize = get_sample_size(format->format) * format->channel_count; 29 30 fPageCount = inBufferCount; 31 fPageSize = frameSize * inBufferFrameCount; 32 fBufferSize = fPageSize * fPageCount; 33 34 fBuffer = new char[fBufferSize]; 35 } 36 37 38 BPushGameSound::BPushGameSound(BGameSoundDevice * device) 39 : BStreamingGameSound(device), 40 fLockPos(0), 41 fPlayPos(0), 42 fBuffer(NULL), 43 fPageSize(0), 44 fPageCount(0), 45 fBufferSize(0) 46 { 47 fPageLocked = new BList; 48 } 49 50 51 BPushGameSound::~BPushGameSound() 52 { 53 delete [] fBuffer; 54 delete fPageLocked; 55 } 56 57 58 BPushGameSound::lock_status 59 BPushGameSound::LockNextPage(void **out_pagePtr, size_t *out_pageSize) 60 { 61 // the user can not lock every page 62 if (fPageLocked->CountItems() > fPageCount - 3) 63 return lock_failed; 64 65 // the user cann't lock a page being played 66 if (fLockPos < fPlayPos 67 && fLockPos + fPageSize > fPlayPos) 68 return lock_failed; 69 70 // lock the page 71 char * lockPage = &fBuffer[fLockPos]; 72 fPageLocked->AddItem(lockPage); 73 74 // move the locker to the next page 75 fLockPos += fPageSize; 76 if (fLockPos > fBufferSize) 77 fLockPos = 0; 78 79 *out_pagePtr = lockPage; 80 *out_pageSize = fPageSize; 81 82 return lock_ok; 83 } 84 85 86 status_t 87 BPushGameSound::UnlockPage(void *in_pagePtr) 88 { 89 return (fPageLocked->RemoveItem(in_pagePtr)) ? B_OK : B_ERROR; 90 } 91 92 93 BPushGameSound::lock_status 94 BPushGameSound::LockForCyclic(void **out_basePtr, size_t *out_size) 95 { 96 *out_basePtr = fBuffer; 97 *out_size = fBufferSize; 98 return lock_ok; 99 } 100 101 102 status_t 103 BPushGameSound::UnlockCyclic() 104 { 105 return B_OK; 106 } 107 108 109 size_t 110 BPushGameSound::CurrentPosition() 111 { 112 return fPlayPos; 113 } 114 115 116 BGameSound * 117 BPushGameSound::Clone() const 118 { 119 gs_audio_format format = Format(); 120 size_t frameSize = get_sample_size(format.format) * format.channel_count; 121 size_t bufferFrameCount = fPageSize / frameSize; 122 123 return new BPushGameSound(bufferFrameCount, &format, fPageCount, Device()); 124 } 125 126 127 status_t 128 BPushGameSound::Perform(int32 selector, void *data) 129 { 130 return BStreamingGameSound::Perform(selector, data); 131 } 132 133 134 status_t 135 BPushGameSound::SetParameters(size_t inBufferFrameCount, 136 const gs_audio_format *format, 137 size_t inBufferCount) 138 { 139 return B_UNSUPPORTED; 140 } 141 142 143 status_t 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 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 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 /* unimplemented for protection of the user: 214 * 215 * BPushGameSound::BPushGameSound() 216 * BPushGameSound::BPushGameSound(const BPushGameSound &) 217 * BPushGameSound &BPushGameSound::operator=(const BPushGameSound &) 218 */ 219 220 221 status_t 222 BPushGameSound::_Reserved_BPushGameSound_0(int32 arg, ...) 223 { 224 return B_ERROR; 225 } 226 227 228 status_t 229 BPushGameSound::_Reserved_BPushGameSound_1(int32 arg, ...) 230 { 231 return B_ERROR; 232 } 233 234 235 status_t 236 BPushGameSound::_Reserved_BPushGameSound_2(int32 arg, ...) 237 { 238 return B_ERROR; 239 } 240 241 242 status_t 243 BPushGameSound::_Reserved_BPushGameSound_3(int32 arg, ...) 244 { 245 return B_ERROR; 246 } 247 248 249 status_t 250 BPushGameSound::_Reserved_BPushGameSound_4(int32 arg, ...) 251 { 252 return B_ERROR; 253 } 254 255 256 status_t 257 BPushGameSound::_Reserved_BPushGameSound_5(int32 arg, ...) 258 { 259 return B_ERROR; 260 } 261 262 263 status_t 264 BPushGameSound::_Reserved_BPushGameSound_6(int32 arg, ...) 265 { 266 return B_ERROR; 267 } 268 269 270 status_t 271 BPushGameSound::_Reserved_BPushGameSound_7(int32 arg, ...) 272 { 273 return B_ERROR; 274 } 275 276 277 status_t 278 BPushGameSound::_Reserved_BPushGameSound_8(int32 arg, ...) 279 { 280 return B_ERROR; 281 } 282 283 284 status_t 285 BPushGameSound::_Reserved_BPushGameSound_9(int32 arg, ...) 286 { 287 return B_ERROR; 288 } 289 290 291 status_t 292 BPushGameSound::_Reserved_BPushGameSound_10(int32 arg, ...) 293 { 294 return B_ERROR; 295 } 296 297 298 status_t 299 BPushGameSound::_Reserved_BPushGameSound_11(int32 arg, ...) 300 { 301 return B_ERROR; 302 } 303 304 305 status_t 306 BPushGameSound::_Reserved_BPushGameSound_12(int32 arg, ...) 307 { 308 return B_ERROR; 309 } 310 311 312 status_t 313 BPushGameSound::_Reserved_BPushGameSound_13(int32 arg, ...) 314 { 315 return B_ERROR; 316 } 317 318 319 status_t 320 BPushGameSound::_Reserved_BPushGameSound_14(int32 arg, ...) 321 { 322 return B_ERROR; 323 } 324 325 326 status_t 327 BPushGameSound::_Reserved_BPushGameSound_15(int32 arg, ...) 328 { 329 return B_ERROR; 330 } 331 332 333 status_t 334 BPushGameSound::_Reserved_BPushGameSound_16(int32 arg, ...) 335 { 336 return B_ERROR; 337 } 338 339 340 status_t 341 BPushGameSound::_Reserved_BPushGameSound_17(int32 arg, ...) 342 { 343 return B_ERROR; 344 } 345 346 347 status_t 348 BPushGameSound::_Reserved_BPushGameSound_18(int32 arg, ...) 349 { 350 return B_ERROR; 351 } 352 353 354 status_t 355 BPushGameSound::_Reserved_BPushGameSound_19(int32 arg, ...) 356 { 357 return B_ERROR; 358 } 359 360 361 status_t 362 BPushGameSound::_Reserved_BPushGameSound_20(int32 arg, ...) 363 { 364 return B_ERROR; 365 } 366 367 368 status_t 369 BPushGameSound::_Reserved_BPushGameSound_21(int32 arg, ...) 370 { 371 return B_ERROR; 372 } 373 374 375 status_t 376 BPushGameSound::_Reserved_BPushGameSound_22(int32 arg, ...) 377 { 378 return B_ERROR; 379 } 380 381 382 status_t 383 BPushGameSound::_Reserved_BPushGameSound_23(int32 arg, ...) 384 { 385 return B_ERROR; 386 } 387 388 389