1*4703fb5dSbeveloper //------------------------------------------------------------------------------ 2*4703fb5dSbeveloper // Copyright (c) 2001-2002, OpenBeOS 3*4703fb5dSbeveloper // 4*4703fb5dSbeveloper // Permission is hereby granted, free of charge, to any person obtaining a 5*4703fb5dSbeveloper // copy of this software and associated documentation files (the "Software"), 6*4703fb5dSbeveloper // to deal in the Software without restriction, including without limitation 7*4703fb5dSbeveloper // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*4703fb5dSbeveloper // and/or sell copies of the Software, and to permit persons to whom the 9*4703fb5dSbeveloper // Software is furnished to do so, subject to the following conditions: 10*4703fb5dSbeveloper // 11*4703fb5dSbeveloper // The above copyright notice and this permission notice shall be included in 12*4703fb5dSbeveloper // all copies or substantial portions of the Software. 13*4703fb5dSbeveloper // 14*4703fb5dSbeveloper // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15*4703fb5dSbeveloper // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16*4703fb5dSbeveloper // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17*4703fb5dSbeveloper // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18*4703fb5dSbeveloper // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19*4703fb5dSbeveloper // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20*4703fb5dSbeveloper // DEALINGS IN THE SOFTWARE. 21*4703fb5dSbeveloper // 22*4703fb5dSbeveloper // File Name: GameSound.cpp 23*4703fb5dSbeveloper // Author: Christopher ML Zumwalt May (zummy@users.sf.net) 24*4703fb5dSbeveloper // Description: BPushGameSound class 25*4703fb5dSbeveloper //------------------------------------------------------------------------------ 260b4a36abSbeveloper 27*4703fb5dSbeveloper // Standard Includes ----------------------------------------------------------- 28*4703fb5dSbeveloper 29*4703fb5dSbeveloper // System Includes ------------------------------------------------------------- 30*4703fb5dSbeveloper #include <List.h> 31*4703fb5dSbeveloper 32*4703fb5dSbeveloper // Project Includes ------------------------------------------------------------ 33*4703fb5dSbeveloper #include <GSUtility.h> 34*4703fb5dSbeveloper 35*4703fb5dSbeveloper // Local Includes -------------------------------------------------------------- 360b4a36abSbeveloper #include <PushGameSound.h> 370b4a36abSbeveloper 38*4703fb5dSbeveloper // Local Defines --------------------------------------------------------------- 390b4a36abSbeveloper 40*4703fb5dSbeveloper // BPushGameSound -------------------------------------------------------------- 410b4a36abSbeveloper BPushGameSound::BPushGameSound(size_t inBufferFrameCount, 420b4a36abSbeveloper const gs_audio_format *format, 430b4a36abSbeveloper size_t inBufferCount, 440b4a36abSbeveloper BGameSoundDevice *device) 45*4703fb5dSbeveloper : BStreamingGameSound(inBufferFrameCount, format, inBufferCount, device) 460b4a36abSbeveloper { 47*4703fb5dSbeveloper if (InitCheck() == B_OK) 48*4703fb5dSbeveloper { 49*4703fb5dSbeveloper status_t error = SetParameters(inBufferFrameCount, format, inBufferCount); 50*4703fb5dSbeveloper if (error != B_OK) 51*4703fb5dSbeveloper fPageLocked = new BList; 52*4703fb5dSbeveloper else 53*4703fb5dSbeveloper SetInitError(error); 54*4703fb5dSbeveloper } 550b4a36abSbeveloper } 560b4a36abSbeveloper 570b4a36abSbeveloper 58*4703fb5dSbeveloper BPushGameSound::BPushGameSound(BGameSoundDevice * device) 59*4703fb5dSbeveloper : BStreamingGameSound(device), 60*4703fb5dSbeveloper fLockPos(0), 61*4703fb5dSbeveloper fPlayPos(0), 62*4703fb5dSbeveloper fBuffer(NULL), 63*4703fb5dSbeveloper fPageSize(0), 64*4703fb5dSbeveloper fPageCount(0), 65*4703fb5dSbeveloper fBufferSize(0) 66*4703fb5dSbeveloper { 67*4703fb5dSbeveloper fPageLocked = new BList; 68*4703fb5dSbeveloper } 69*4703fb5dSbeveloper 700b4a36abSbeveloper BPushGameSound::~BPushGameSound() 710b4a36abSbeveloper { 72*4703fb5dSbeveloper delete [] fBuffer; 73*4703fb5dSbeveloper delete fPageLocked; 740b4a36abSbeveloper } 750b4a36abSbeveloper 760b4a36abSbeveloper 770b4a36abSbeveloper BPushGameSound::lock_status 780b4a36abSbeveloper BPushGameSound::LockNextPage(void **out_pagePtr, 790b4a36abSbeveloper size_t *out_pageSize) 800b4a36abSbeveloper { 81*4703fb5dSbeveloper // the user can not lock every page 82*4703fb5dSbeveloper if (fPageLocked->CountItems() > fPageCount - 3) return lock_failed; 83*4703fb5dSbeveloper 84*4703fb5dSbeveloper // the user cann't lock a page being played 85*4703fb5dSbeveloper if (fLockPos < fPlayPos && fLockPos + fPageSize > fPlayPos) return lock_failed; 86*4703fb5dSbeveloper 87*4703fb5dSbeveloper // lock the page 88*4703fb5dSbeveloper char * lockPage = &fBuffer[fLockPos]; 89*4703fb5dSbeveloper fPageLocked->AddItem(lockPage); 90*4703fb5dSbeveloper 91*4703fb5dSbeveloper // move the locker to the next page 92*4703fb5dSbeveloper fLockPos += fPageSize; 93*4703fb5dSbeveloper if (fLockPos > fBufferSize) fLockPos = 0; 94*4703fb5dSbeveloper 95*4703fb5dSbeveloper *out_pagePtr = lockPage; 96*4703fb5dSbeveloper *out_pageSize = fPageSize; 97*4703fb5dSbeveloper 98*4703fb5dSbeveloper return lock_ok; 990b4a36abSbeveloper } 1000b4a36abSbeveloper 1010b4a36abSbeveloper 1020b4a36abSbeveloper status_t 1030b4a36abSbeveloper BPushGameSound::UnlockPage(void *in_pagePtr) 1040b4a36abSbeveloper { 105*4703fb5dSbeveloper return (fPageLocked->RemoveItem(in_pagePtr)) ? B_OK : B_ERROR; 1060b4a36abSbeveloper } 1070b4a36abSbeveloper 1080b4a36abSbeveloper 1090b4a36abSbeveloper BPushGameSound::lock_status 1100b4a36abSbeveloper BPushGameSound::LockForCyclic(void **out_basePtr, 1110b4a36abSbeveloper size_t *out_size) 1120b4a36abSbeveloper { 113*4703fb5dSbeveloper *out_basePtr = fBuffer; 114*4703fb5dSbeveloper *out_size = fBufferSize; 115*4703fb5dSbeveloper return lock_ok; 1160b4a36abSbeveloper } 1170b4a36abSbeveloper 1180b4a36abSbeveloper 1190b4a36abSbeveloper status_t 1200b4a36abSbeveloper BPushGameSound::UnlockCyclic() 1210b4a36abSbeveloper { 122*4703fb5dSbeveloper return B_OK; 1230b4a36abSbeveloper } 1240b4a36abSbeveloper 1250b4a36abSbeveloper 1260b4a36abSbeveloper size_t 1270b4a36abSbeveloper BPushGameSound::CurrentPosition() 1280b4a36abSbeveloper { 129*4703fb5dSbeveloper return fPlayPos; 1300b4a36abSbeveloper } 1310b4a36abSbeveloper 1320b4a36abSbeveloper 1330b4a36abSbeveloper BGameSound * 1340b4a36abSbeveloper BPushGameSound::Clone() const 1350b4a36abSbeveloper { 136*4703fb5dSbeveloper gs_audio_format format = Format(); 137*4703fb5dSbeveloper size_t frameSize = get_sample_size(format.format) * format.channel_count; 138*4703fb5dSbeveloper size_t bufferFrameCount = fPageSize / frameSize; 139*4703fb5dSbeveloper 140*4703fb5dSbeveloper return new BPushGameSound(bufferFrameCount, &format, fPageCount, Device()); 1410b4a36abSbeveloper } 1420b4a36abSbeveloper 1430b4a36abSbeveloper 1440b4a36abSbeveloper status_t 1450b4a36abSbeveloper BPushGameSound::Perform(int32 selector, 1460b4a36abSbeveloper void *data) 1470b4a36abSbeveloper { 1480b4a36abSbeveloper return B_ERROR; 1490b4a36abSbeveloper } 1500b4a36abSbeveloper 1510b4a36abSbeveloper 1520b4a36abSbeveloper status_t 1530b4a36abSbeveloper BPushGameSound::SetParameters(size_t inBufferFrameCount, 1540b4a36abSbeveloper const gs_audio_format *format, 1550b4a36abSbeveloper size_t inBufferCount) 1560b4a36abSbeveloper { 157*4703fb5dSbeveloper status_t error = BStreamingGameSound::SetParameters(inBufferFrameCount, format, inBufferCount); 158*4703fb5dSbeveloper if (error != B_OK) return error; 159*4703fb5dSbeveloper 160*4703fb5dSbeveloper size_t frameSize = get_sample_size(format->format) * format->channel_count; 161*4703fb5dSbeveloper 162*4703fb5dSbeveloper fPageCount = inBufferCount; 163*4703fb5dSbeveloper fPageSize = frameSize * inBufferFrameCount; 164*4703fb5dSbeveloper fBufferSize = fPageSize * fPageCount; 165*4703fb5dSbeveloper 166*4703fb5dSbeveloper fBuffer = new char[fBufferSize]; 167*4703fb5dSbeveloper 168*4703fb5dSbeveloper return B_OK; 1690b4a36abSbeveloper } 1700b4a36abSbeveloper 1710b4a36abSbeveloper 1720b4a36abSbeveloper status_t 1730b4a36abSbeveloper BPushGameSound::SetStreamHook(void (*hook)(void * inCookie, void * inBuffer, size_t inByteCount, BStreamingGameSound * me), 1740b4a36abSbeveloper void * cookie) 1750b4a36abSbeveloper { 1760b4a36abSbeveloper return B_ERROR; 1770b4a36abSbeveloper } 1780b4a36abSbeveloper 1790b4a36abSbeveloper 1800b4a36abSbeveloper void 1810b4a36abSbeveloper BPushGameSound::FillBuffer(void *inBuffer, 1820b4a36abSbeveloper size_t inByteCount) 1830b4a36abSbeveloper { 184*4703fb5dSbeveloper size_t bytes = inByteCount; 185*4703fb5dSbeveloper 186*4703fb5dSbeveloper if (BytesReady(&bytes)) 187*4703fb5dSbeveloper { 188*4703fb5dSbeveloper if (fPlayPos + bytes > fBufferSize) 189*4703fb5dSbeveloper { 190*4703fb5dSbeveloper size_t remainder = fPlayPos + bytes - fBufferSize; 191*4703fb5dSbeveloper char * buffer = (char*)inBuffer; 192*4703fb5dSbeveloper 193*4703fb5dSbeveloper // fill the buffer with the samples left at the end of our buffer 194*4703fb5dSbeveloper memcpy(buffer, &fBuffer[fPlayPos], remainder); 195*4703fb5dSbeveloper fPlayPos = 0; 196*4703fb5dSbeveloper 197*4703fb5dSbeveloper // fill the remainder of the buffer by looping to the start 198*4703fb5dSbeveloper // of the buffer if it isn't locked 199*4703fb5dSbeveloper bytes -= remainder; 200*4703fb5dSbeveloper if (BytesReady(&bytes)) 201*4703fb5dSbeveloper { 202*4703fb5dSbeveloper memcpy(&buffer[remainder], fBuffer, bytes); 203*4703fb5dSbeveloper fPlayPos += bytes; 204*4703fb5dSbeveloper } 205*4703fb5dSbeveloper } 206*4703fb5dSbeveloper else 207*4703fb5dSbeveloper { 208*4703fb5dSbeveloper memcpy(inBuffer, &fBuffer[fPlayPos], bytes); 209*4703fb5dSbeveloper fPlayPos += bytes; 2100b4a36abSbeveloper } 2110b4a36abSbeveloper 212*4703fb5dSbeveloper BStreamingGameSound::FillBuffer(inBuffer, inByteCount); 213*4703fb5dSbeveloper } 214*4703fb5dSbeveloper } 215*4703fb5dSbeveloper 216*4703fb5dSbeveloper 217*4703fb5dSbeveloper bool 218*4703fb5dSbeveloper BPushGameSound::BytesReady(size_t * bytes) 219*4703fb5dSbeveloper { 220*4703fb5dSbeveloper if (fPageLocked->CountItems() > 0) 221*4703fb5dSbeveloper { 222*4703fb5dSbeveloper size_t start = fPlayPos; 223*4703fb5dSbeveloper size_t ready = fPlayPos; 224*4703fb5dSbeveloper int32 page = int32(start / fPageSize); 225*4703fb5dSbeveloper 226*4703fb5dSbeveloper // return if there is nothing to do 227*4703fb5dSbeveloper if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) return false; 228*4703fb5dSbeveloper 229*4703fb5dSbeveloper while (ready < *bytes) 230*4703fb5dSbeveloper { 231*4703fb5dSbeveloper ready += fPageSize; 232*4703fb5dSbeveloper page = int32(ready / fPageSize); 233*4703fb5dSbeveloper 234*4703fb5dSbeveloper if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) 235*4703fb5dSbeveloper { 236*4703fb5dSbeveloper // we have found a locked page 237*4703fb5dSbeveloper *bytes = ready - start - (ready - page * fPageSize); 238*4703fb5dSbeveloper return true; 239*4703fb5dSbeveloper } 240*4703fb5dSbeveloper } 241*4703fb5dSbeveloper } 242*4703fb5dSbeveloper 243*4703fb5dSbeveloper // all of the bytes are ready 244*4703fb5dSbeveloper return true; 245*4703fb5dSbeveloper } 2460b4a36abSbeveloper 2470b4a36abSbeveloper /* unimplemented for protection of the user: 2480b4a36abSbeveloper * 2490b4a36abSbeveloper * BPushGameSound::BPushGameSound() 2500b4a36abSbeveloper * BPushGameSound::BPushGameSound(const BPushGameSound &) 2510b4a36abSbeveloper * BPushGameSound &BPushGameSound::operator=(const BPushGameSound &) 2520b4a36abSbeveloper */ 2530b4a36abSbeveloper 2540b4a36abSbeveloper 2550b4a36abSbeveloper status_t 2560b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_0(int32 arg, ...) 2570b4a36abSbeveloper { 2580b4a36abSbeveloper return B_ERROR; 2590b4a36abSbeveloper } 2600b4a36abSbeveloper 2610b4a36abSbeveloper 2620b4a36abSbeveloper status_t 2630b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_1(int32 arg, ...) 2640b4a36abSbeveloper { 2650b4a36abSbeveloper return B_ERROR; 2660b4a36abSbeveloper } 2670b4a36abSbeveloper 2680b4a36abSbeveloper 2690b4a36abSbeveloper status_t 2700b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_2(int32 arg, ...) 2710b4a36abSbeveloper { 2720b4a36abSbeveloper return B_ERROR; 2730b4a36abSbeveloper } 2740b4a36abSbeveloper 2750b4a36abSbeveloper 2760b4a36abSbeveloper status_t 2770b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_3(int32 arg, ...) 2780b4a36abSbeveloper { 2790b4a36abSbeveloper return B_ERROR; 2800b4a36abSbeveloper } 2810b4a36abSbeveloper 2820b4a36abSbeveloper 2830b4a36abSbeveloper status_t 2840b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_4(int32 arg, ...) 2850b4a36abSbeveloper { 2860b4a36abSbeveloper return B_ERROR; 2870b4a36abSbeveloper } 2880b4a36abSbeveloper 2890b4a36abSbeveloper 2900b4a36abSbeveloper status_t 2910b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_5(int32 arg, ...) 2920b4a36abSbeveloper { 2930b4a36abSbeveloper return B_ERROR; 2940b4a36abSbeveloper } 2950b4a36abSbeveloper 2960b4a36abSbeveloper 2970b4a36abSbeveloper status_t 2980b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_6(int32 arg, ...) 2990b4a36abSbeveloper { 3000b4a36abSbeveloper return B_ERROR; 3010b4a36abSbeveloper } 3020b4a36abSbeveloper 3030b4a36abSbeveloper 3040b4a36abSbeveloper status_t 3050b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_7(int32 arg, ...) 3060b4a36abSbeveloper { 3070b4a36abSbeveloper return B_ERROR; 3080b4a36abSbeveloper } 3090b4a36abSbeveloper 3100b4a36abSbeveloper 3110b4a36abSbeveloper status_t 3120b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_8(int32 arg, ...) 3130b4a36abSbeveloper { 3140b4a36abSbeveloper return B_ERROR; 3150b4a36abSbeveloper } 3160b4a36abSbeveloper 3170b4a36abSbeveloper 3180b4a36abSbeveloper status_t 3190b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_9(int32 arg, ...) 3200b4a36abSbeveloper { 3210b4a36abSbeveloper return B_ERROR; 3220b4a36abSbeveloper } 3230b4a36abSbeveloper 3240b4a36abSbeveloper 3250b4a36abSbeveloper status_t 3260b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_10(int32 arg, ...) 3270b4a36abSbeveloper { 3280b4a36abSbeveloper return B_ERROR; 3290b4a36abSbeveloper } 3300b4a36abSbeveloper 3310b4a36abSbeveloper 3320b4a36abSbeveloper status_t 3330b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_11(int32 arg, ...) 3340b4a36abSbeveloper { 3350b4a36abSbeveloper return B_ERROR; 3360b4a36abSbeveloper } 3370b4a36abSbeveloper 3380b4a36abSbeveloper 3390b4a36abSbeveloper status_t 3400b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_12(int32 arg, ...) 3410b4a36abSbeveloper { 3420b4a36abSbeveloper return B_ERROR; 3430b4a36abSbeveloper } 3440b4a36abSbeveloper 3450b4a36abSbeveloper 3460b4a36abSbeveloper status_t 3470b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_13(int32 arg, ...) 3480b4a36abSbeveloper { 3490b4a36abSbeveloper return B_ERROR; 3500b4a36abSbeveloper } 3510b4a36abSbeveloper 3520b4a36abSbeveloper 3530b4a36abSbeveloper status_t 3540b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_14(int32 arg, ...) 3550b4a36abSbeveloper { 3560b4a36abSbeveloper return B_ERROR; 3570b4a36abSbeveloper } 3580b4a36abSbeveloper 3590b4a36abSbeveloper 3600b4a36abSbeveloper status_t 3610b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_15(int32 arg, ...) 3620b4a36abSbeveloper { 3630b4a36abSbeveloper return B_ERROR; 3640b4a36abSbeveloper } 3650b4a36abSbeveloper 3660b4a36abSbeveloper 3670b4a36abSbeveloper status_t 3680b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_16(int32 arg, ...) 3690b4a36abSbeveloper { 3700b4a36abSbeveloper return B_ERROR; 3710b4a36abSbeveloper } 3720b4a36abSbeveloper 3730b4a36abSbeveloper 3740b4a36abSbeveloper status_t 3750b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_17(int32 arg, ...) 3760b4a36abSbeveloper { 3770b4a36abSbeveloper return B_ERROR; 3780b4a36abSbeveloper } 3790b4a36abSbeveloper 3800b4a36abSbeveloper 3810b4a36abSbeveloper status_t 3820b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_18(int32 arg, ...) 3830b4a36abSbeveloper { 3840b4a36abSbeveloper return B_ERROR; 3850b4a36abSbeveloper } 3860b4a36abSbeveloper 3870b4a36abSbeveloper 3880b4a36abSbeveloper status_t 3890b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_19(int32 arg, ...) 3900b4a36abSbeveloper { 3910b4a36abSbeveloper return B_ERROR; 3920b4a36abSbeveloper } 3930b4a36abSbeveloper 3940b4a36abSbeveloper 3950b4a36abSbeveloper status_t 3960b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_20(int32 arg, ...) 3970b4a36abSbeveloper { 3980b4a36abSbeveloper return B_ERROR; 3990b4a36abSbeveloper } 4000b4a36abSbeveloper 4010b4a36abSbeveloper 4020b4a36abSbeveloper status_t 4030b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_21(int32 arg, ...) 4040b4a36abSbeveloper { 4050b4a36abSbeveloper return B_ERROR; 4060b4a36abSbeveloper } 4070b4a36abSbeveloper 4080b4a36abSbeveloper 4090b4a36abSbeveloper status_t 4100b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_22(int32 arg, ...) 4110b4a36abSbeveloper { 4120b4a36abSbeveloper return B_ERROR; 4130b4a36abSbeveloper } 4140b4a36abSbeveloper 4150b4a36abSbeveloper 4160b4a36abSbeveloper status_t 4170b4a36abSbeveloper BPushGameSound::_Reserved_BPushGameSound_23(int32 arg, ...) 4180b4a36abSbeveloper { 4190b4a36abSbeveloper return B_ERROR; 4200b4a36abSbeveloper } 4210b4a36abSbeveloper 4220b4a36abSbeveloper 423