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