|
|
/*************************************************
* waveodev.cpp * * * * Copyright (C) 1995-1999 Microsoft Inc. * * * *************************************************/
// waveodev.cpp : implementation file
//
#include "stdafx.h"
#include "wave.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__; #endif
// global items
CWaveOutDevice theDefaultWaveOutDevice;
/////////////////////////////////////////////////////////////////////////////
// CWaveOutDevice
CWaveOutDevice::CWaveOutDevice() { m_hOutDev = NULL; m_iBlockCount = 0; }
CWaveOutDevice::~CWaveOutDevice() { }
BEGIN_MESSAGE_MAP(CWaveOutDevice, CWnd) //{{AFX_MSG_MAP(CWaveOutDevice)
ON_MESSAGE(MM_WOM_DONE, OnWomDone) //}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CWaveOutDevice::Create() { if (!CreateEx(0, AfxRegisterWndClass(0), "Wave Wnd", WS_POPUP, 0, 0, 0, 0, NULL, NULL)) { TRACE("Failed to create wave notification window"); return FALSE; } return TRUE; }
#ifndef _DEBUG
#define MMERR(n) 0
#else
void MMERR(MMRESULT mmr) { switch (mmr) { case WAVERR_BADFORMAT: TRACE("No wave device supports format"); break; case MMSYSERR_NOMEM: TRACE("Out of memory"); break; case MMSYSERR_ALLOCATED: TRACE("Resource is already allocated"); break; case MMSYSERR_BADDEVICEID: TRACE("Bad device id"); break; case MMSYSERR_INVALHANDLE: TRACE("Invalid device handle"); break; case MMSYSERR_HANDLEBUSY: TRACE("Device in use by another thread"); break; case WAVERR_UNPREPARED: TRACE("Header not prepared"); break; default: TRACE("Unknown error"); break; } } #endif // _DEBUG
/////////////////////////////////////////////////////////////////////////////
// CWaveOutDevice message handlers
LRESULT CWaveOutDevice::OnWomDone(WPARAM w, LPARAM l) { ASSERT(l); WAVEHDR* phdr = (WAVEHDR*) l; CWave* pWave = (CWave*)(phdr->dwUser); ASSERT(pWave->IsKindOf(RUNTIME_CLASS(CWave))); CWaveOutDevice* pOutDev = pWave->GetOutDevice(); ASSERT(pOutDev); pOutDev->WaveOutDone(pWave, phdr); UNREFERENCED_PARAMETER(w); return 0; }
BOOL CWaveOutDevice::IsOpen() { return m_hOutDev ? TRUE : FALSE; }
BOOL CWaveOutDevice::Open(WAVEFORMATEX *pFormat) { MMRESULT mmr;
// Make sure we have a callback window.
if (!m_hWnd) { Create(); // Create the window.
ASSERT(m_hWnd); }
// See whether it's already open for this format.
if (IsOpen()) { // See whether it can handle this format.
if (CanDoFormat(pFormat)) { return TRUE; } else { TRACE("Open for different format"); return FALSE; } }
// See whether we can open for this format.
mmr = waveOutOpen(&m_hOutDev, WAVE_MAPPER, pFormat, (DWORD_PTR)(GetSafeHwnd()), 0, CALLBACK_WINDOW); if (mmr != 0) { MMERR(mmr); return FALSE; }
return TRUE; }
BOOL CWaveOutDevice::CanDoFormat(WAVEFORMATEX* pFormat) { MMRESULT mmr;
if (!IsOpen()) { TRACE("Not open"); return FALSE; } HWAVEOUT hDev = NULL; mmr = waveOutOpen(&hDev, WAVE_MAPPER, pFormat, NULL, 0, WAVE_FORMAT_QUERY); if (mmr != 0) { MMERR(mmr); return FALSE; } return TRUE; }
BOOL CWaveOutDevice::Close() { if (m_hOutDev) { // Close the device.
waveOutReset(m_hOutDev); MMRESULT mmr = waveOutClose(m_hOutDev); if (mmr != 0) { MMERR(mmr); } m_hOutDev = NULL; } // Destroy the window.
DestroyWindow(); ASSERT(m_hWnd == NULL); return TRUE; }
BOOL CWaveOutDevice::Play(CWave* pWave) { if (!Open(pWave->GetFormat())) { return FALSE; }
// Allocate a header.
WAVEHDR* phdr = (WAVEHDR*)malloc(sizeof(WAVEHDR)); ASSERT(phdr); // Fill out the wave header.
memset(phdr, 0, sizeof(WAVEHDR)); //#if 1 // BUGFIX for VC++ 2.0
// phdr->lpData = (BYTE*) pWave->GetSamples();
//#else
phdr->lpData = (char*) pWave->GetSamples(); //#endif
phdr->dwBufferLength = pWave->GetSize(); phdr->dwUser = (DWORD_PTR)(void*)pWave; // So we can find the object
// Prepare the header
MMRESULT mmr = waveOutPrepareHeader(m_hOutDev, phdr, sizeof(WAVEHDR)); if (mmr) { MMERR(mmr); return FALSE; } // Mark the wave as busy.
pWave->SetBusy(TRUE);
// Start it playing.
mmr = waveOutWrite(m_hOutDev, phdr, sizeof(WAVEHDR)); if (mmr) { MMERR(mmr); return FALSE; }
// Add one to the block count.
m_iBlockCount++;
return TRUE; }
void CWaveOutDevice::WaveOutDone(CWave *pWave, WAVEHDR *pHdr) { // Unprepare the header.
MMRESULT mmr = waveOutUnprepareHeader(m_hOutDev, pHdr, sizeof(WAVEHDR)); if (mmr) { MMERR(mmr); } // Free the header.
free(pHdr);
// Decrement the block count.
ASSERT(m_iBlockCount > 0); m_iBlockCount--; if (m_iBlockCount == 0) { // Close the device.
Close(); }
// Notify the object that it is done.
pWave->SetBusy(FALSE); pWave->OnWaveOutDone(); }
|