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