Функция обратного вызова в API waveOutOpen () - PullRequest
0 голосов
/ 03 апреля 2012

Я создаю аудиоплеер, который воспроизводит файлы «.wav», и у меня возникла проблема с функцией обратного вызова, вызываемой из waveOutOpen () API.

Открытие выходного аудиоустройства для воспроизведения:

 MMRESULT mRes = waveOutOpen(m_hWO,WAVE_MAPPER,&wFmt,(DWORD)&waveOutProc,(DWORD)this, 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;
    }
}

Проблема в том, что MM_WOM_DONE никогда не возникает, и функция обратного вызова никогда не вызывается после завершения воспроизведения файла. Если вместо функции обратного вызова необходимо использовать поток, может кто-нибудь дать мне простой пример того, как использовать поток обратного вызова (не найден в сети).

Также документация waveOutReset () предполагает, что он закрывает все буферы и возвращает систему, поэтому для обработки кнопки Stop в моем приложении я использовал функцию waveOutReset (), но это привело к зависанию приложения. Почему это происходит? Есть ли альтернативный способ остановить воспроизведение, когда буфер все еще находится в очереди на воспроизведение.

Ответы [ 2 ]

1 голос
/ 27 мая 2012

Функция обратного вызова, вероятно, не может быть методом вашего класса CPlayWave.Это должна быть простая функция вашего класса с запрошенным прототипом.

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

Конечно, она должна быть объявлена ​​/ определена перед вызовом waveOutOpen ().Кроме того, имя функции является указателем и амперсанд & не требуется.Таким образом, вызов waveOutOpen () должен быть:

MMRESULT mRes = waveOutOpen(m_hWO, WAVE_MAPPER, &wFmt, (DWORD_PTR) waveOutProc, (DWORD_PTR) this, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
0 голосов
/ 31 августа 2018

Также у вас есть только несколько системных функций, которые вы можете вызвать из waveOutProc:

"Приложения не должны вызывать какие-либо системные функции из функции обратного вызова, кроме EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent и timeSetEvent. Вызов других волновых функций вызовет взаимоблокировку. "

Поэтому вызов функций, таких как AfxMessageBox или waveOutUnprepareHeader, может вызвать ужасные проблемы.

...