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