📄 hsound.cpp
字号:
mmioClose(hmmio, 0);
dwDataSize = 0;
return NULL;
}
/* We're done with the file, let's close it */
mmioClose(hmmio, 0);
if (!m_bContinue)
{
free(lpWaveFmt);
free(lpData);
dwDataSize = 0;
return NULL;
}
return lpData;
}
/*****************************************************************
* Pauses playing
*****************************************************************/
BOOL CHSound::Pause()
{
return FALSE;
}
/*****************************************************************
* Stops playing
*****************************************************************/
BOOL CHSound::Stop()
{
return FALSE;
}
/*****************************************************************
* Closes the device
*****************************************************************/
BOOL CHSound::Close()
{
m_bContinue = FALSE;
m_bForceClose = TRUE;
SetStatus(STT_RSTTING);
MMRESULT mmRes = waveOutReset(m_hWaveOut);
int ptcn = 0;
/* If we were playng */
if (mmRes==0) {
while(GetStatus()!=STT_ASLEEP) {
WaitForSingleObject(m_hStatEvent,100);
if (ptcn++>10) break;
ResetEvent(m_hStatEvent);
}
// return TRUE;
}
KillTimer();
CleanPlayList();
SetStatus(STT_ASLEEP);
return TRUE;
}
/*****************************************************************
* Indicates wheather this device is playing a sound or not
*****************************************************************/
BOOL CHSound::IsPlaying()
{
if (GetStatus()==STT_PLAYING)
return TRUE;
return FALSE;
}
/*****************************************************************
* Thread to receive and process sound messages
******************************************************************
*
* MSDN says it's not possible to do waveOutUnprepareHeader in the
* callback function, so I do it here + I do cleanup.
*
*****************************************************************/
UINT CHSound::CallBackThread(LPVOID pParam)
{
CHSound* pParent = (CHSound*) pParam;
MSG msg;
while (m_bThreadContinue) {
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
/* One file playback is done */
if ( msg.message==MM_WOM_DONE ) {
if (msg.lParam)
pParent->PlayNextBuffer(msg);/* Inform parent */
}
} else Sleep(5);
}
return 0;
}
void CHSound::SetStatus(DWORD dwCurStat)
{
EnterCriticalSection(&m_statusCrtcSec);
m_dwStatus ^= m_dwStatus;
m_dwStatus |= dwCurStat;
LeaveCriticalSection(&m_statusCrtcSec);
SetEvent(m_hStatEvent);
}
DWORD CHSound::GetStatus()
{
return m_dwStatus;
}
void CHSound::PlayNextBuffer(MSG msg)
{
if (!m_bContinue) {
goto PNB_EXIT;
// Any more buffers to read?
} else if (m_dwCurrtBufIndex<m_dwBufCnt) {
mmRes = waveOutWrite(
m_hWaveOut,
m_lpWHdr,
sizeof(WAVEHDR) );
/* Can't Do the last job :(( */
if ( MMSYSERR_NOERROR != mmRes ) {
SetStatus(STT_RSTTING);
waveOutUnprepareHeader(m_hWaveOut,m_lpWHdr,sizeof(WAVEHDR));
SetStatus(STT_CLOSING);
waveOutClose(m_hWaveOut);
goto PNB_EXIT;
}
// Prepare next buffer
m_dwCurrtBufIndex++;
if ((m_dwCurrtBufIndex+1)==m_dwBufCnt) {
m_dwBLength =
m_dwDataSize-((m_dwCurrtBufIndex)*m_dwMinBufSize);
} else {
m_dwBLength = m_dwMinBufSize;
}
m_lpBuf2 += m_dwMinBufSize;
m_lpWHdr->lpData = m_lpBuf2;
m_lpWHdr->dwBufferLength = m_dwBLength;
} else {
// m_dwCurrtBufIndex = 0;
// m_dwBufCnt = 0;
goto PNB_EXIT;
}
return;
PNB_EXIT:;
SetStatus(STT_RSTTING);
m_lpWHdr->dwBufferLength = m_dwDataSize;
m_lpWHdr->lpData = m_lpData;
waveOutUnprepareHeader(
m_hWaveOut,
m_lpWHdr,
sizeof(WAVEHDR));
SetStatus(STT_CLOSING);
/* close wave device */
waveOutClose((HWAVEOUT)msg.wParam);
/* free the wave data */
SetStatus(STT_RSTTING);
free (m_lpData);
free (m_lpWHdr); /* free the header */
SetStatus(STT_ASLEEP);
if (m_bContinue)
PlayNextFile();
}
BOOL CHSound::PlayNextFile()
{
if (!m_bContinue) return FALSE;
int patience = 0,retryP = 0;
CString str = _T("");
retry:;
patience = 0;
/* Give me next file to play */
/* If, for any reason, FileName is empty */
while (str==_T("")) {
str = m_playList.GetNext();
if (++patience>1000) return FALSE;
if (!m_bContinue) return FALSE;
}
/* If play list is finished */
if ( str == _T("END_OF_LIST") ) {
if (m_bExitAfter) {
KillTimer();
PostThreadMessage(m_boss,WM_SOUND_DONE,1,0);
} else {
/* Playback ended, so set a timer to */
SetTimer(); /* restart playing last menu */
} /* in an interval */
return TRUE;
} else if ( str==_T("DELAY")) {
if (!m_bContinue) return FALSE;
Sleep(500);
str = _T("");
patience = 0;
goto retry;
}
/* We are going to play, so tell the timer to shut up! */
KillTimer();
/* Start playback */
if (!Play( m_dwDevId, str )) {
if (!m_bContinue) return FALSE;
else {
TRACE(L"Cant play [%s] \n",str);
/* Skip this file if can't play */
if (++retryP>10) {
retryP = 0;
str=_T("");
}
// Sleep(100);
goto retry;
}
}
return TRUE;
}
/*****************************************************************
* We need a window to start or kill a timer. I'm too lazy writing
* my own class!
******************************************************************
*
* WARNING: If you need a timer, rhis function MUST be called
* In a class that has a pointer to a dialog, or any
* type of a window, & the window MUST process Timer
* events. Look at DaliaDlg here.
*
*****************************************************************/
void CHSound::SetTimerWindow(CWnd *wndTimer)
{
m_wndTimer = wndTimer;
}
/*****************************************************************
* Sets a timer
*****************************************************************/
void CHSound::SetTimer()
{
if (m_wndTimer) {
if (m_wndTimer->GetSafeHwnd())
m_wndTimer->SendMessage(
WM_S_TIMER, SET,0);
}
}
/*****************************************************************
* Kills the timer, though No more notifications
*****************************************************************/
void CHSound::KillTimer()
{
if (m_wndTimer) {
if (m_wndTimer->GetSafeHwnd())
m_wndTimer->SendMessage(
WM_S_TIMER, KILL,0);
}
}
/*****************************************************************
* Start playing 'play list'
*****************************************************************/
BOOL CHSound::PlayList(DWORD dwDeviceId, BOOL bExitAfter, BOOL bDisableForceExit)
{
if (m_bForceClose && (!bDisableForceExit) ) return FALSE;
if (bDisableForceExit) {
m_bForceClose = FALSE;
}
m_dwDevId = dwDeviceId;
m_bExitAfter = bExitAfter;
m_bContinue = TRUE;
/* Now start playing new list */
return PlayNextFile();
}
/*****************************************************************
* Adds a file to our 'play list'
*****************************************************************/
void CHSound::AddToPlayList(CString szWaveFile)
{
m_playList.Add(szWaveFile);
}
/*****************************************************************
* Removes all files from the 'play list'
*****************************************************************/
void CHSound::CleanPlayList()
{
m_playList.Reset();
}
/*****************************************************************
* Makes sound class ready to get new inputs
*****************************************************************/
BOOL CHSound::Reset()
{
EnterCriticalSection(&m_externalResetCrtcSec);
if (GetStatus()==STT_EXTRNRS ||
!m_bContinue) {
LeaveCriticalSection(&m_externalResetCrtcSec);
return FALSE;
}
LeaveCriticalSection(&m_externalResetCrtcSec);
m_bContinue = FALSE;
SetStatus(STT_EXTRNRS);
MMRESULT mmRes = waveOutReset(m_hWaveOut);
int ptcn = 0;
/* If we were playng */
if (mmRes==0) {
while(GetStatus()!=STT_ASLEEP) {
WaitForSingleObject(m_hStatEvent,100);
if (ptcn++>10) break;
ResetEvent(m_hStatEvent);
}
// return TRUE;
}
KillTimer();
CleanPlayList();
SetStatus(STT_ASLEEP);
return TRUE;
}
/*****************************************************************
* Set a thread ID and use it to talk to parent manager
*****************************************************************/
void CHSound::SetManager(unsigned long mngrThread)
{
m_boss = mngrThread;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -