219 lines
6 KiB
C++
219 lines
6 KiB
C++
#include "linux/windows/dsound.h"
|
|
#include "linux/windows/winerror.h"
|
|
#include "linux/interface.h"
|
|
|
|
#include <cstring>
|
|
|
|
HRESULT IDirectSoundNotify::SetNotificationPositions(DWORD cPositionNotifies, LPCDSBPOSITIONNOTIFY lpcPositionNotifies)
|
|
{
|
|
return DS_OK;
|
|
}
|
|
|
|
IDirectSoundBuffer::IDirectSoundBuffer(const size_t aBufferSize, const size_t aChannels, const size_t aSampleRate, const size_t aBitsPerSample, const size_t aFlags)
|
|
: bufferSize(aBufferSize)
|
|
, channels(aChannels)
|
|
, sampleRate(aSampleRate)
|
|
, bitsPerSample(aBitsPerSample)
|
|
, flags(aFlags)
|
|
, mySoundNotify(new IDirectSoundNotify)
|
|
, mySoundBuffer(aBufferSize)
|
|
{
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::Release()
|
|
{
|
|
// unregister *before* the destructor is called (in Release below)
|
|
// makes things a little bit more linear
|
|
unregisterSoundBuffer(this);
|
|
|
|
// do not call any more methods after the next function returns
|
|
return IUnknown::Release();
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::QueryInterface(int riid, void **ppvObject)
|
|
{
|
|
if (riid == IID_IDirectSoundNotify)
|
|
{
|
|
*ppvObject = mySoundNotify.get();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::Unlock( LPVOID lpvAudioPtr1, DWORD dwAudioBytes1, LPVOID lpvAudioPtr2, DWORD dwAudioBytes2 )
|
|
{
|
|
const size_t totalWrittenBytes = dwAudioBytes1 + dwAudioBytes2;
|
|
this->myWritePosition = (this->myWritePosition + totalWrittenBytes) % this->mySoundBuffer.size();
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::Stop()
|
|
{
|
|
const DWORD mask = DSBSTATUS_PLAYING | DSBSTATUS_LOOPING;
|
|
this->myStatus &= ~mask;
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::SetCurrentPosition( DWORD dwNewPosition )
|
|
{
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::Play( DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags )
|
|
{
|
|
this->myStatus |= DSBSTATUS_PLAYING;
|
|
if (dwFlags & DSBPLAY_LOOPING)
|
|
{
|
|
this->myStatus |= DSBSTATUS_LOOPING;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::SetVolume( LONG lVolume )
|
|
{
|
|
this->myVolume = lVolume;
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::GetStatus( LPDWORD lpdwStatus )
|
|
{
|
|
*lpdwStatus = this->myStatus;
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::Restore()
|
|
{
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::Lock( DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID * lplpvAudioPtr1, DWORD * lpdwAudioBytes1, LPVOID * lplpvAudioPtr2, DWORD * lpdwAudioBytes2, DWORD dwFlags )
|
|
{
|
|
// No attempt is made at restricting write buffer not to overtake play cursor
|
|
if (dwFlags & DSBLOCK_ENTIREBUFFER)
|
|
{
|
|
*lplpvAudioPtr1 = this->mySoundBuffer.data();
|
|
*lpdwAudioBytes1 = this->mySoundBuffer.size();
|
|
if (lplpvAudioPtr2 && lpdwAudioBytes2)
|
|
{
|
|
*lplpvAudioPtr2 = nullptr;
|
|
*lpdwAudioBytes2 = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const DWORD availableInFirstPart = this->mySoundBuffer.size() - dwWriteCursor;
|
|
|
|
*lplpvAudioPtr1 = this->mySoundBuffer.data() + dwWriteCursor;
|
|
*lpdwAudioBytes1 = std::min(availableInFirstPart, dwWriteBytes);
|
|
|
|
if (lplpvAudioPtr2 && lpdwAudioBytes2)
|
|
{
|
|
if (*lpdwAudioBytes1 < dwWriteBytes)
|
|
{
|
|
*lplpvAudioPtr2 = this->mySoundBuffer.data();
|
|
*lpdwAudioBytes2 = std::min(dwWriteCursor, dwWriteBytes - *lpdwAudioBytes1);
|
|
}
|
|
else
|
|
{
|
|
*lplpvAudioPtr2 = nullptr;
|
|
*lpdwAudioBytes2 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::Read( DWORD dwReadBytes, LPVOID * lplpvAudioPtr1, DWORD * lpdwAudioBytes1, LPVOID * lplpvAudioPtr2, DWORD * lpdwAudioBytes2)
|
|
{
|
|
// Read up to dwReadBytes, never going past the write cursor
|
|
// Positions are updated immediately
|
|
const DWORD available = (this->myWritePosition - this->myPlayPosition) % this->bufferSize;
|
|
dwReadBytes = std::min(dwReadBytes, available);
|
|
|
|
const DWORD availableInFirstPart = this->mySoundBuffer.size() - this->myPlayPosition;
|
|
|
|
*lplpvAudioPtr1 = this->mySoundBuffer.data() + this->myPlayPosition;
|
|
*lpdwAudioBytes1 = std::min(availableInFirstPart, dwReadBytes);
|
|
|
|
if (lplpvAudioPtr2 && lpdwAudioBytes2)
|
|
{
|
|
if (*lpdwAudioBytes1 < dwReadBytes)
|
|
{
|
|
*lplpvAudioPtr2 = this->mySoundBuffer.data();
|
|
*lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
|
|
}
|
|
else
|
|
{
|
|
*lplpvAudioPtr2 = nullptr;
|
|
*lpdwAudioBytes2 = 0;
|
|
}
|
|
}
|
|
this->myPlayPosition = (this->myPlayPosition + dwReadBytes) % this->mySoundBuffer.size();
|
|
return DS_OK;
|
|
}
|
|
|
|
DWORD IDirectSoundBuffer::GetBytesInBuffer() const
|
|
{
|
|
const DWORD available = (this->myWritePosition - this->myPlayPosition) % this->bufferSize;
|
|
return available;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::GetCurrentPosition( LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor )
|
|
{
|
|
*lpdwCurrentPlayCursor = this->myPlayPosition;
|
|
*lpdwCurrentWriteCursor = this->myWritePosition;
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSoundBuffer::GetVolume( LONG * lplVolume )
|
|
{
|
|
*lplVolume = this->myVolume;
|
|
return DS_OK;
|
|
}
|
|
|
|
double IDirectSoundBuffer::GetLogarithmicVolume() const
|
|
{
|
|
const double volume = (double(myVolume) - DSBVOLUME_MIN) / (0.0 - DSBVOLUME_MIN);
|
|
return volume;
|
|
}
|
|
|
|
HRESULT WINAPI DirectSoundCreate(LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter)
|
|
{
|
|
*ppDS = new IDirectSound();
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT DirectSoundEnumerate(LPDSENUMCALLBACK lpDSEnumCallback, LPVOID lpContext)
|
|
{
|
|
GUID guid = 123;
|
|
lpDSEnumCallback(&guid, "audio", "linux", lpContext);
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSound::CreateSoundBuffer( LPCDSBUFFERDESC lpcDSBufferDesc, IDirectSoundBuffer **lplpDirectSoundBuffer, IUnknown FAR* pUnkOuter )
|
|
{
|
|
const size_t bufferSize = lpcDSBufferDesc->dwBufferBytes;
|
|
const size_t channels = lpcDSBufferDesc->lpwfxFormat->nChannels;
|
|
const size_t sampleRate = lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec;
|
|
const size_t bitsPerSample = lpcDSBufferDesc->lpwfxFormat->wBitsPerSample;
|
|
const size_t flags = lpcDSBufferDesc->dwFlags;
|
|
IDirectSoundBuffer * dsb = new IDirectSoundBuffer(bufferSize, channels, sampleRate, bitsPerSample, flags);
|
|
|
|
registerSoundBuffer(dsb);
|
|
|
|
*lplpDirectSoundBuffer = dsb;
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSound::SetCooperativeLevel( HWND hwnd, DWORD dwLevel )
|
|
{
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT IDirectSound::GetCaps(LPDSCCAPS pDSCCaps)
|
|
{
|
|
memset(pDSCCaps, 0, sizeof(*pDSCCaps));
|
|
return DS_OK;
|
|
}
|