Etapa 6: Manipular eventos do Graph
[O recurso associado a esta página, DirectShow, é um recurso herdado. Ele foi substituído por MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo na Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]
Este tópico é a etapa 6 do tutorial Reprodução de Áudio/Vídeo no DirectShow. O código completo é mostrado no tópico Exemplo de Reprodução do DirectShow.
Quando o aplicativo cria uma nova instância do Gerenciador de Grafo de Filtro, o aplicativo chama IMediaEventEx::SetNotifyWindow. Esse método registra a janela do aplicativo para receber eventos do grafo de filtro.
hr = m_pGraph->QueryInterface(IID_PPV_ARGS(&m_pEvent));
if (FAILED(hr))
{
goto done;
}
// Set up event notification.
hr = m_pEvent->SetNotifyWindow((OAHWND)m_hwnd, WM_GRAPH_EVENT, NULL);
if (FAILED(hr))
{
goto done;
}
O valor WM_GRAPH_EVENT
é uma mensagem de janela privada. Sempre que o aplicativo recebe essa mensagem, ele chama o DShowPlayer::HandleGraphEvent
método .
case WM_GRAPH_EVENT:
g_pPlayer->HandleGraphEvent(OnGraphEvent);
return 0;
O método DShowPlayer::HandleGraphEvent
faz o seguinte:
- Chama IMediaEvent::GetEvent em um loop para obter todos os eventos enfileirados.
- Invoca uma função de retorno de chamada (pfnOnGraphEvent).
- Chama IMediaEvent::FreeEventParams para liberar os dados associados a cada evento.
// Respond to a graph event.
//
// The owning window should call this method when it receives the window
// message that the application specified when it called SetEventWindow.
//
// Caution: Do not tear down the graph from inside the callback.
HRESULT DShowPlayer::HandleGraphEvent(GraphEventFN pfnOnGraphEvent)
{
if (!m_pEvent)
{
return E_UNEXPECTED;
}
long evCode = 0;
LONG_PTR param1 = 0, param2 = 0;
HRESULT hr = S_OK;
// Get the events from the queue.
while (SUCCEEDED(m_pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0)))
{
// Invoke the callback.
pfnOnGraphEvent(m_hwnd, evCode, param1, param2);
// Free the event data.
hr = m_pEvent->FreeEventParams(evCode, param1, param2);
if (FAILED(hr))
{
break;
}
}
return hr;
}
O código a seguir mostra a função de retorno de chamada que é passada para DShowPlayer::HandleGraphEvent
. A função manipula o número mínimo de eventos de grafo (EC_COMPLETE, EC_ERRORABORT e EC_USERABORT); você pode expandir a função para lidar com eventos adicionais.
void CALLBACK OnGraphEvent(HWND hwnd, long evCode, LONG_PTR param1, LONG_PTR param2)
{
switch (evCode)
{
case EC_COMPLETE:
case EC_USERABORT:
g_pPlayer->Stop();
break;
case EC_ERRORABORT:
NotifyError(hwnd, L"Playback error.");
g_pPlayer->Stop();
break;
}
}
Tópicos relacionados