#include WaveOutDevice::WaveOutDevice(UINT waveDeviceID,Window &windowHandler) : mWaveDeviceID(waveDeviceID), mhWaveOut(0), mGlobalWaveHeader(1,GMEM_MOVEABLE|GMEM_ZEROINIT), mWindowHandler(windowHandler), DeviceHandler(windowHandler), mDisposition(InClose) { ::waveOutGetDevCaps(mWaveDeviceID,&((WAVEOUTCAPS&)mWaveOutCaps),sizeof(mWaveOutCaps)); } WaveOutDevice::WaveOutDevice(const WaveOutDevice &someWaveOutDevice) : mWindowHandler(someWaveOutDevice.mWindowHandler), mhWaveOut(0), mGlobalWaveHeader(1,GMEM_MOVEABLE|GMEM_ZEROINIT), mWaveDeviceID(someWaveOutDevice.mWaveDeviceID), DeviceHandler(someWaveOutDevice.mWindowHandler), mDisposition(someWaveOutDevice.mDisposition) { *this=someWaveOutDevice; } WaveOutDevice::~WaveOutDevice() { closeDevice(); } WaveOutDevice &WaveOutDevice::operator=(const WaveOutDevice &someWaveOutDevice) { mWaveOutCaps=someWaveOutDevice.mWaveOutCaps; return *this; } BOOL WaveOutDevice::openDevice(WaveFormatPCM &waveFormatPCM) { MMRESULT mmResult; closeDevice(); mmResult=::waveOutOpen(&mhWaveOut,mWaveDeviceID,(LPWAVEFORMATEX)&waveFormatPCM,(UINT)((HWND)mWindowHandler),0L,WAVE_ALLOWSYNC|CALLBACK_WINDOW); if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;} mDisposition=InOpen; return TRUE; } BOOL WaveOutDevice::closeDevice(void) { MMRESULT mmResult; if(!mhWaveOut||InClose==mDisposition)return TRUE; if(InPlay==mDisposition) { mmResult=::waveOutReset(mhWaveOut); if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;} } while(InPlay==mDisposition)mWindowHandler.yieldTask(); mmResult=::waveOutClose(mhWaveOut); if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;} mDisposition=InClose; mhWaveOut=0; return TRUE; } BOOL WaveOutDevice::pause(void) { MMRESULT mmResult; if(InPlay!=mDisposition)return FALSE; if(0!=(mmResult=::waveOutPause(mhWaveOut))){mmSystemErrorMessage(mmResult);return FALSE;} mDisposition=InPause; return TRUE; } BOOL WaveOutDevice::restart(void) { MMRESULT mmResult; if(InPause!=mDisposition)return FALSE; if(0!=(mmResult=::waveOutRestart(mhWaveOut))){mmSystemErrorMessage(mmResult);return FALSE;} mDisposition=InPlay; return TRUE; } BOOL WaveOutDevice::play(WaveForm &someWaveForm,DeviceHandler::PlayMode playMode) { MMRESULT mmResult; WaveFormatPCM waveFormatPCM(someWaveForm.getFormatChunk()); if(WaveFormatEx::PulseCodeModulation!=waveFormatPCM.formatTag()){genericErrorMessage(InvalidFormat);return FALSE;} if(!openDevice(waveFormatPCM))return FALSE; ((WaveHeader*)&mGlobalWaveHeader[0])->setData((char*)(someWaveForm.getPureSample().sampleData())); ((WaveHeader*)&mGlobalWaveHeader[0])->setBufferLength(someWaveForm.getPureSample().numSamples()); ((WaveHeader*)&mGlobalWaveHeader[0])->userData((DWORD)this); mmResult=::waveOutPrepareHeader(mhWaveOut,(WAVEHDR*)((WaveHeader*)&mGlobalWaveHeader[0]),sizeof(WAVEHDR)); if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;} mmResult=::waveOutWrite(mhWaveOut,(WAVEHDR*)((WaveHeader*)&mGlobalWaveHeader[0]),sizeof(WAVEHDR)); if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;} mDisposition=InPlay; if(mmResult){mmSystemErrorMessage(mmResult);unprepareHeader();return FALSE;} if(DeviceHandler::Wait==playMode) { while(InPlay==mDisposition)mWindowHandler.yieldTask(); closeDevice(); } return TRUE; } void WaveOutDevice::unprepareHeader(void) { if(!mhWaveOut){genericErrorMessage(DeviceHandler::InvalidDeviceHandle);return;} if(!mGlobalWaveHeader.isOkay()){genericErrorMessage(DeviceHandler::InvalidHeader);return;} ::waveOutUnprepareHeader(mhWaveOut,(WAVEHDR*)((WaveHeader*)&mGlobalWaveHeader[0]),sizeof(WaveHeader)); } // virtuals void WaveOutDevice::openHandler(CallbackData &/*someCallbackData*/) { return; } void WaveOutDevice::closeHandler(CallbackData &/*someCallbackData*/) { return; } void WaveOutDevice::doneHandler(CallbackData &someCallbackData) { WaveHeader &waveHeader=(*((WaveHeader*)someCallbackData.lParam())); if(waveHeader.userData()==(DWORD)this) { unprepareHeader(); mDisposition=InIdle; } return; } void WaveOutDevice::message(const String &strErrorMessage)const { ::OutputDebugString((String&)strErrorMessage+String("\n")); }