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 19BPushGameSound::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 39BPushGameSound::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 52BPushGameSound::~BPushGameSound() 53{ 54 delete [] fBuffer; 55 delete fPageLocked; 56} 57 58 59BPushGameSound::lock_status 60BPushGameSound::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 87status_t 88BPushGameSound::UnlockPage(void *in_pagePtr) 89{ 90 return (fPageLocked->RemoveItem(in_pagePtr)) ? B_OK : B_ERROR; 91} 92 93 94BPushGameSound::lock_status 95BPushGameSound::LockForCyclic(void **out_basePtr, size_t *out_size) 96{ 97 *out_basePtr = fBuffer; 98 *out_size = fBufferSize; 99 return lock_ok; 100} 101 102 103status_t 104BPushGameSound::UnlockCyclic() 105{ 106 return B_OK; 107} 108 109 110size_t 111BPushGameSound::CurrentPosition() 112{ 113 return fPlayPos; 114} 115 116 117BGameSound * 118BPushGameSound::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 128status_t 129BPushGameSound::Perform(int32 selector, void *data) 130{ 131 return BStreamingGameSound::Perform(selector, data); 132} 133 134 135status_t 136BPushGameSound::SetParameters(size_t inBufferFrameCount, 137 const gs_audio_format *format, size_t inBufferCount) 138{ 139 return B_UNSUPPORTED; 140} 141 142 143status_t 144BPushGameSound::SetStreamHook(void (*hook)(void * inCookie, void * inBuffer, 145 size_t inByteCount, BStreamingGameSound * me), void * cookie) 146{ 147 return B_UNSUPPORTED; 148} 149 150 151void 152BPushGameSound::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 184bool 185BPushGameSound::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 222status_t 223BPushGameSound::_Reserved_BPushGameSound_0(int32 arg, ...) 224{ 225 return B_ERROR; 226} 227 228 229status_t 230BPushGameSound::_Reserved_BPushGameSound_1(int32 arg, ...) 231{ 232 return B_ERROR; 233} 234 235 236status_t 237BPushGameSound::_Reserved_BPushGameSound_2(int32 arg, ...) 238{ 239 return B_ERROR; 240} 241 242 243status_t 244BPushGameSound::_Reserved_BPushGameSound_3(int32 arg, ...) 245{ 246 return B_ERROR; 247} 248 249 250status_t 251BPushGameSound::_Reserved_BPushGameSound_4(int32 arg, ...) 252{ 253 return B_ERROR; 254} 255 256 257status_t 258BPushGameSound::_Reserved_BPushGameSound_5(int32 arg, ...) 259{ 260 return B_ERROR; 261} 262 263 264status_t 265BPushGameSound::_Reserved_BPushGameSound_6(int32 arg, ...) 266{ 267 return B_ERROR; 268} 269 270 271status_t 272BPushGameSound::_Reserved_BPushGameSound_7(int32 arg, ...) 273{ 274 return B_ERROR; 275} 276 277 278status_t 279BPushGameSound::_Reserved_BPushGameSound_8(int32 arg, ...) 280{ 281 return B_ERROR; 282} 283 284 285status_t 286BPushGameSound::_Reserved_BPushGameSound_9(int32 arg, ...) 287{ 288 return B_ERROR; 289} 290 291 292status_t 293BPushGameSound::_Reserved_BPushGameSound_10(int32 arg, ...) 294{ 295 return B_ERROR; 296} 297 298 299status_t 300BPushGameSound::_Reserved_BPushGameSound_11(int32 arg, ...) 301{ 302 return B_ERROR; 303} 304 305 306status_t 307BPushGameSound::_Reserved_BPushGameSound_12(int32 arg, ...) 308{ 309 return B_ERROR; 310} 311 312 313status_t 314BPushGameSound::_Reserved_BPushGameSound_13(int32 arg, ...) 315{ 316 return B_ERROR; 317} 318 319 320status_t 321BPushGameSound::_Reserved_BPushGameSound_14(int32 arg, ...) 322{ 323 return B_ERROR; 324} 325 326 327status_t 328BPushGameSound::_Reserved_BPushGameSound_15(int32 arg, ...) 329{ 330 return B_ERROR; 331} 332 333 334status_t 335BPushGameSound::_Reserved_BPushGameSound_16(int32 arg, ...) 336{ 337 return B_ERROR; 338} 339 340 341status_t 342BPushGameSound::_Reserved_BPushGameSound_17(int32 arg, ...) 343{ 344 return B_ERROR; 345} 346 347 348status_t 349BPushGameSound::_Reserved_BPushGameSound_18(int32 arg, ...) 350{ 351 return B_ERROR; 352} 353 354 355status_t 356BPushGameSound::_Reserved_BPushGameSound_19(int32 arg, ...) 357{ 358 return B_ERROR; 359} 360 361 362status_t 363BPushGameSound::_Reserved_BPushGameSound_20(int32 arg, ...) 364{ 365 return B_ERROR; 366} 367 368 369status_t 370BPushGameSound::_Reserved_BPushGameSound_21(int32 arg, ...) 371{ 372 return B_ERROR; 373} 374 375 376status_t 377BPushGameSound::_Reserved_BPushGameSound_22(int32 arg, ...) 378{ 379 return B_ERROR; 380} 381 382 383status_t 384BPushGameSound::_Reserved_BPushGameSound_23(int32 arg, ...) 385{ 386 return B_ERROR; 387} 388