/* * Copyright 2001-2012 Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Christopher ML Zumwalt May (zummy@users.sf.net) * Jérôme Duval */ #include #include #include #include "GSUtility.h" BPushGameSound::BPushGameSound(size_t inBufferFrameCount, const gs_audio_format *format, size_t inBufferCount, BGameSoundDevice *device) : BStreamingGameSound(inBufferFrameCount, format, inBufferCount, device), fLockPos(0), fPlayPos(0) { fPageLocked = new BList; size_t frameSize = get_sample_size(format->format) * format->channel_count; fPageCount = inBufferCount; fPageSize = frameSize * inBufferFrameCount; fBufferSize = fPageSize * fPageCount; fBuffer = new char[fBufferSize]; } BPushGameSound::BPushGameSound(BGameSoundDevice * device) : BStreamingGameSound(device), fLockPos(0), fPlayPos(0), fBuffer(NULL), fPageSize(0), fPageCount(0), fBufferSize(0) { fPageLocked = new BList; } BPushGameSound::~BPushGameSound() { delete [] fBuffer; delete fPageLocked; } BPushGameSound::lock_status BPushGameSound::LockNextPage(void **out_pagePtr, size_t *out_pageSize) { // the user can not lock every page if (fPageLocked->CountItems() > fPageCount - 1) return lock_failed; // the user can't lock a page being played if (fLockPos < fPlayPos && fLockPos + fPageSize > fPlayPos) return lock_failed; // lock the page char * lockPage = &fBuffer[fLockPos]; fPageLocked->AddItem(lockPage); // move the locker to the next page fLockPos += fPageSize; if (fLockPos >= fBufferSize) fLockPos = 0; *out_pagePtr = lockPage; *out_pageSize = fPageSize; return lock_ok; } status_t BPushGameSound::UnlockPage(void *in_pagePtr) { return (fPageLocked->RemoveItem(in_pagePtr)) ? B_OK : B_ERROR; } BPushGameSound::lock_status BPushGameSound::LockForCyclic(void **out_basePtr, size_t *out_size) { *out_basePtr = fBuffer; *out_size = fBufferSize; return lock_ok; } status_t BPushGameSound::UnlockCyclic() { return B_OK; } size_t BPushGameSound::CurrentPosition() { return fPlayPos; } BGameSound * BPushGameSound::Clone() const { gs_audio_format format = Format(); size_t frameSize = get_sample_size(format.format) * format.channel_count; size_t bufferFrameCount = fPageSize / frameSize; return new BPushGameSound(bufferFrameCount, &format, fPageCount, Device()); } status_t BPushGameSound::Perform(int32 selector, void *data) { return BStreamingGameSound::Perform(selector, data); } status_t BPushGameSound::SetParameters(size_t inBufferFrameCount, const gs_audio_format *format, size_t inBufferCount) { return B_UNSUPPORTED; } status_t BPushGameSound::SetStreamHook(void (*hook)(void * inCookie, void * inBuffer, size_t inByteCount, BStreamingGameSound * me), void * cookie) { return B_UNSUPPORTED; } void BPushGameSound::FillBuffer(void *inBuffer, size_t inByteCount) { size_t bytes = inByteCount; if (!BytesReady(&bytes)) return; if (fPlayPos + bytes > fBufferSize) { size_t remainder = fBufferSize - fPlayPos; // Space left in buffer char * buffer = (char*)inBuffer; // fill the buffer with the samples left at the end of our buffer memcpy(buffer, &fBuffer[fPlayPos], remainder); fPlayPos = 0; // fill the remainder of the buffer by looping to the start // of the buffer if it isn't locked bytes -= remainder; if (BytesReady(&bytes)) { memcpy(&buffer[remainder], fBuffer, bytes); fPlayPos += bytes; } } else { memcpy(inBuffer, &fBuffer[fPlayPos], bytes); fPlayPos += bytes; } BStreamingGameSound::FillBuffer(inBuffer, inByteCount); } bool BPushGameSound::BytesReady(size_t * bytes) { if (fPageLocked->CountItems() <= 0) return true; size_t start = fPlayPos; size_t ready = fPlayPos; int32 page = int32(start / fPageSize); // return if there is nothing to do if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) return false; while (ready < *bytes) { ready += fPageSize; page = int32(ready / fPageSize); if (fPageLocked->HasItem(&fBuffer[page * fPageSize])) { // we have found a locked page *bytes = ready - start - (ready - page * fPageSize); return true; } } // all of the bytes are ready return true; } /* unimplemented for protection of the user: * * BPushGameSound::BPushGameSound() * BPushGameSound::BPushGameSound(const BPushGameSound &) * BPushGameSound &BPushGameSound::operator=(const BPushGameSound &) */ status_t BPushGameSound::_Reserved_BPushGameSound_0(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_1(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_2(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_3(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_4(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_5(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_6(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_7(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_8(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_9(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_10(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_11(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_12(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_13(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_14(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_15(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_16(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_17(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_18(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_19(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_20(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_21(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_22(int32 arg, ...) { return B_ERROR; } status_t BPushGameSound::_Reserved_BPushGameSound_23(int32 arg, ...) { return B_ERROR; }