1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: GameSound.cpp 23 // Author: Christopher ML Zumwalt May (zummy@users.sf.net) 24 // Description: BPushGameSound class 25 //------------------------------------------------------------------------------ 26 27 // Standard Includes ----------------------------------------------------------- 28 29 // System Includes ------------------------------------------------------------- 30 #include <List.h> 31 32 // Project Includes ------------------------------------------------------------ 33 #include <GSUtility.h> 34 35 // Local Includes -------------------------------------------------------------- 36 #include <PushGameSound.h> 37 38 // Local Defines --------------------------------------------------------------- 39 40 // BPushGameSound -------------------------------------------------------------- 41 BPushGameSound::BPushGameSound(size_t inBufferFrameCount, 42 const gs_audio_format *format, 43 size_t inBufferCount, 44 BGameSoundDevice *device) 45 : BStreamingGameSound(inBufferFrameCount, format, inBufferCount, device) 46 { 47 if (InitCheck() == B_OK) 48 { 49 status_t error = SetParameters(inBufferFrameCount, format, inBufferCount); 50 if (error != B_OK) 51 fPageLocked = new BList; 52 else 53 SetInitError(error); 54 } 55 } 56 57 58 BPushGameSound::BPushGameSound(BGameSoundDevice * device) 59 : BStreamingGameSound(device), 60 fLockPos(0), 61 fPlayPos(0), 62 fBuffer(NULL), 63 fPageSize(0), 64 fPageCount(0), 65 fBufferSize(0) 66 { 67 fPageLocked = new BList; 68 } 69 70 BPushGameSound::~BPushGameSound() 71 { 72 delete [] fBuffer; 73 delete fPageLocked; 74 } 75 76 77 BPushGameSound::lock_status 78 BPushGameSound::LockNextPage(void **out_pagePtr, 79 size_t *out_pageSize) 80 { 81 // the user can not lock every page 82 if (fPageLocked->CountItems() > fPageCount - 3) return lock_failed; 83 84 // the user cann't lock a page being played 85 if (fLockPos < fPlayPos && fLockPos + fPageSize > fPlayPos) return lock_failed; 86 87 // lock the page 88 char * lockPage = &fBuffer[fLockPos]; 89 fPageLocked->AddItem(lockPage); 90 91 // move the locker to the next page 92 fLockPos += fPageSize; 93 if (fLockPos > fBufferSize) fLockPos = 0; 94 95 *out_pagePtr = lockPage; 96 *out_pageSize = fPageSize; 97 98 return lock_ok; 99 } 100 101 102 status_t 103 BPushGameSound::UnlockPage(void *in_pagePtr) 104 { 105 return (fPageLocked->RemoveItem(in_pagePtr)) ? B_OK : B_ERROR; 106 } 107 108 109 BPushGameSound::lock_status 110 BPushGameSound::LockForCyclic(void **out_basePtr, 111 size_t *out_size) 112 { 113 *out_basePtr = fBuffer; 114 *out_size = fBufferSize; 115 return lock_ok; 116 } 117 118 119 status_t 120 BPushGameSound::UnlockCyclic() 121 { 122 return B_OK; 123 } 124 125 126 size_t 127 BPushGameSound::CurrentPosition() 128 { 129 return fPlayPos; 130 } 131 132 133 BGameSound * 134 BPushGameSound::Clone() const 135 { 136 gs_audio_format format = Format(); 137 size_t frameSize = get_sample_size(format.format) * format.channel_count; 138 size_t bufferFrameCount = fPageSize / frameSize; 139 140 return new BPushGameSound(bufferFrameCount, &format, fPageCount, Device()); 141 } 142 143 144 status_t 145 BPushGameSound::Perform(int32 selector, 146 void *data) 147 { 148 return B_ERROR; 149 } 150 151 152 status_t 153 BPushGameSound::SetParameters(size_t inBufferFrameCount, 154 const gs_audio_format *format, 155 size_t inBufferCount) 156 { 157 status_t error = BStreamingGameSound::SetParameters(inBufferFrameCount, format, inBufferCount); 158 if (error != B_OK) return error; 159 160 size_t frameSize = get_sample_size(format->format) * format->channel_count; 161 162 fPageCount = inBufferCount; 163 fPageSize = frameSize * inBufferFrameCount; 164 fBufferSize = fPageSize * fPageCount; 165 166 fBuffer = new char[fBufferSize]; 167 168 return B_OK; 169 } 170 171 172 status_t 173 BPushGameSound::SetStreamHook(void (*hook)(void * inCookie, void * inBuffer, size_t inByteCount, BStreamingGameSound * me), 174 void * cookie) 175 { 176 return B_ERROR; 177 } 178 179 180 void 181 BPushGameSound::FillBuffer(void *inBuffer, 182 size_t inByteCount) 183 { 184 size_t bytes = inByteCount; 185 186 if (BytesReady(&bytes)) 187 { 188 if (fPlayPos + bytes > fBufferSize) 189 { 190 size_t remainder = fPlayPos + bytes - fBufferSize; 191 char * buffer = (char*)inBuffer; 192 193 // fill the buffer with the samples left at the end of our buffer 194 memcpy(buffer, &fBuffer[fPlayPos], remainder); 195 fPlayPos = 0; 196 197 // fill the remainder of the buffer by looping to the start 198 // of the buffer if it isn't locked 199 bytes -= remainder; 200 if (BytesReady(&bytes)) 201 { 202 memcpy(&buffer[remainder], fBuffer, bytes); 203 fPlayPos += bytes; 204 } 205 } 206 else 207 { 208 memcpy(inBuffer, &fBuffer[fPlayPos], bytes); 209 fPlayPos += bytes; 210 } 211 212 BStreamingGameSound::FillBuffer(inBuffer, inByteCount); 213 } 214 } 215 216 217 bool 218 BPushGameSound::BytesReady(size_t * bytes) 219 { 220 if (fPageLocked->CountItems() > 0) 221 { 222 size_t start = fPlayPos; 223 size_t ready = fPlayPos; 224 int32 page = int32(start / fPageSize); 225 226 // return if there is nothing to do 227 if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) return false; 228 229 while (ready < *bytes) 230 { 231 ready += fPageSize; 232 page = int32(ready / fPageSize); 233 234 if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) 235 { 236 // we have found a locked page 237 *bytes = ready - start - (ready - page * fPageSize); 238 return true; 239 } 240 } 241 } 242 243 // all of the bytes are ready 244 return true; 245 } 246 247 /* unimplemented for protection of the user: 248 * 249 * BPushGameSound::BPushGameSound() 250 * BPushGameSound::BPushGameSound(const BPushGameSound &) 251 * BPushGameSound &BPushGameSound::operator=(const BPushGameSound &) 252 */ 253 254 255 status_t 256 BPushGameSound::_Reserved_BPushGameSound_0(int32 arg, ...) 257 { 258 return B_ERROR; 259 } 260 261 262 status_t 263 BPushGameSound::_Reserved_BPushGameSound_1(int32 arg, ...) 264 { 265 return B_ERROR; 266 } 267 268 269 status_t 270 BPushGameSound::_Reserved_BPushGameSound_2(int32 arg, ...) 271 { 272 return B_ERROR; 273 } 274 275 276 status_t 277 BPushGameSound::_Reserved_BPushGameSound_3(int32 arg, ...) 278 { 279 return B_ERROR; 280 } 281 282 283 status_t 284 BPushGameSound::_Reserved_BPushGameSound_4(int32 arg, ...) 285 { 286 return B_ERROR; 287 } 288 289 290 status_t 291 BPushGameSound::_Reserved_BPushGameSound_5(int32 arg, ...) 292 { 293 return B_ERROR; 294 } 295 296 297 status_t 298 BPushGameSound::_Reserved_BPushGameSound_6(int32 arg, ...) 299 { 300 return B_ERROR; 301 } 302 303 304 status_t 305 BPushGameSound::_Reserved_BPushGameSound_7(int32 arg, ...) 306 { 307 return B_ERROR; 308 } 309 310 311 status_t 312 BPushGameSound::_Reserved_BPushGameSound_8(int32 arg, ...) 313 { 314 return B_ERROR; 315 } 316 317 318 status_t 319 BPushGameSound::_Reserved_BPushGameSound_9(int32 arg, ...) 320 { 321 return B_ERROR; 322 } 323 324 325 status_t 326 BPushGameSound::_Reserved_BPushGameSound_10(int32 arg, ...) 327 { 328 return B_ERROR; 329 } 330 331 332 status_t 333 BPushGameSound::_Reserved_BPushGameSound_11(int32 arg, ...) 334 { 335 return B_ERROR; 336 } 337 338 339 status_t 340 BPushGameSound::_Reserved_BPushGameSound_12(int32 arg, ...) 341 { 342 return B_ERROR; 343 } 344 345 346 status_t 347 BPushGameSound::_Reserved_BPushGameSound_13(int32 arg, ...) 348 { 349 return B_ERROR; 350 } 351 352 353 status_t 354 BPushGameSound::_Reserved_BPushGameSound_14(int32 arg, ...) 355 { 356 return B_ERROR; 357 } 358 359 360 status_t 361 BPushGameSound::_Reserved_BPushGameSound_15(int32 arg, ...) 362 { 363 return B_ERROR; 364 } 365 366 367 status_t 368 BPushGameSound::_Reserved_BPushGameSound_16(int32 arg, ...) 369 { 370 return B_ERROR; 371 } 372 373 374 status_t 375 BPushGameSound::_Reserved_BPushGameSound_17(int32 arg, ...) 376 { 377 return B_ERROR; 378 } 379 380 381 status_t 382 BPushGameSound::_Reserved_BPushGameSound_18(int32 arg, ...) 383 { 384 return B_ERROR; 385 } 386 387 388 status_t 389 BPushGameSound::_Reserved_BPushGameSound_19(int32 arg, ...) 390 { 391 return B_ERROR; 392 } 393 394 395 status_t 396 BPushGameSound::_Reserved_BPushGameSound_20(int32 arg, ...) 397 { 398 return B_ERROR; 399 } 400 401 402 status_t 403 BPushGameSound::_Reserved_BPushGameSound_21(int32 arg, ...) 404 { 405 return B_ERROR; 406 } 407 408 409 status_t 410 BPushGameSound::_Reserved_BPushGameSound_22(int32 arg, ...) 411 { 412 return B_ERROR; 413 } 414 415 416 status_t 417 BPushGameSound::_Reserved_BPushGameSound_23(int32 arg, ...) 418 { 419 return B_ERROR; 420 } 421 422 423