ckram
ckram

Reputation: 19

Callback function in waveOutOpen() API

I am building an audio player that plays '.wav' files and I have a problem with the callback function called from waveOutOpen() API.

Opening the output audio device for playback:

 MMRESULT mRes = waveOutOpen(m_hWO,WAVE_MAPPER,&wFmt,(DWORD)&waveOutProc,(DWORD)this, CALLBACK_FUNCTION);

Implementation of callback function:

void CPlayWave::waveOutProc(HWAVEOUT m_hWO,UINT uMsg,DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
    MMRESULT mmRes;
    CPlayWave *pPW = (CPlayWave*)dwInstance;
    switch(uMsg)
    {
    case MM_WOM_DONE:       //playback finished
        mmRes = waveOutUnprepareHeader(m_hWO, &pPW->m_WHdr, sizeof(WAVEHDR));
        if(mmRes!=MMSYSERR_NOERROR)
        {
            //error handling
            .....
        }
        mmRes = waveOutClose(m_hWO);
        if(mmRes!=MMSYSERR_NOERROR)
        {
            //error handling
            .....
        }
        AfxMessageBox("Finished playing the file");
        m_bPlay = FALSE;      //boolean flag used for pausing
        break;
    case WIM_DATA:
        //for recording completion
        break;
    }
}

The problem is the MM_WOM_DONE never occurs and the callback function is never called after the playback of the file is completed. If a thread has to be used instead of callback function, can someone give me a simple example on how to use a callback thread(haven't found on net).

Also waveOutReset() documentation suggests that it closes all the buffers and returns to the system, so for handling the Stop-button in my application, I used the waveOutReset() function but, this causing the application to freeze. Why is this happening? Is there any alternative method to stop playing while buffer is still in queue for playback.

Upvotes: 1

Views: 4898

Answers (2)

Stormwaker
Stormwaker

Reputation: 391

Also you there are only few system functions you can call from waveOutProc:

"Applications should not call any system-defined functions from inside a callback function, except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock."

So calling funcitons like AfxMessageBox or waveOutUnprepareHeader might be cause terrible issues.

Upvotes: 1

Roman
Roman

Reputation: 21

Callback function probably can not be a method of your class CPlayWave itself. It must be simple function out of your class with requested prototype.

void CALLBACK waveOutProc(HWAVEOUT m_hWO, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
  ...
}

It must be, of course, declared/defined before you call waveOutOpen(). In addition, function name is pointer itself and ampersand & is not needed. Thus calling waveOutOpen() should be:

MMRESULT mRes = waveOutOpen(m_hWO, WAVE_MAPPER, &wFmt, (DWORD_PTR) waveOutProc, (DWORD_PTR) this, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);

Upvotes: 2

Related Questions