HRESULT CPlayer::Invoke(IMFAsyncResult *pResult) { HRESULT hr = S_OK; MediaEventType meType = MEUnknown; // Event type IMFMediaEvent *pEvent = NULL; // Get the event from the event queue. CHECK_HR(hr = m_pSession->EndGetEvent(pResult, &pEvent)); // Get the event type. CHECK_HR(hr = pEvent->GetType(&meType)); // If the session is closed, the application is waiting on the // m_hCloseEvent event handle. Also, do not get any more // events from the session. if (meType == MESessionClosed) { SetEvent(m_hCloseEvent); } else { // For all other events, ask the media session for the // next event in the queue. CHECK_HR(hr = m_pSession->BeginGetEvent(this, NULL)); } // For most events, we post the event as a private window message to the // application. This lets the application process the event on it's // main thread. // However, if call to IMFMediaSession::Close is pending, it means the // application is waiting on the m_hCloseEvent event handle. (Blocking // call.) In that case, we simply discard the event. // NOTE: When IMFMediaSession::Close is called, MESessionClosed is NOT // necessarily the next event that we will receive. We may receive // any number of other events before receiving MESessionClosed. if (m_state != Closing) { // Leave a reference count on the event. pEvent->AddRef(); PostMessage(m_hwndEvent, WM_APP_PLAYER_EVENT, (WPARAM)pEvent, (LPARAM)0); } done: SAFE_RELEASE(pEvent); return S_OK; }
// Callback for the asynchronous BeginGetEvent method. HRESULT CPlayer::Invoke(IMFAsyncResult *pResult) { MediaEventType meType = MEUnknown; // Event type IMFMediaEvent *pEvent = NULL; HRESULT hr; if ( !m_pSession ) { CI_LOG_W("Called with a null session"); return -1; //Sometimes Invoke is called but m_pSession is closed } // Handle async-loading if ( m_state == OpenAsyncPending ) { if ( !&m_pSourceResolver ) { CI_LOG_E("Async request returned with NULL session"); //ofLogError( "CPlayer::Invoke" ) << "Async request returned with NULL session"; return -1; } MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID; IUnknown *pSourceUnk = NULL; //CheckPointer(m_pSource, E_POINTER); hr = m_pSourceResolver->EndCreateObjectFromURL( pResult, // Invoke result &ObjectType, // Receives the created object type. &pSourceUnk // Receives a pointer to the media source. ); // Get the IMFMediaSource interface from the media source. if ( SUCCEEDED( hr ) ) { hr = pSourceUnk->QueryInterface( __uuidof( IMFMediaSource ), (void**) ( &m_pSource ) ); m_state = OpenAsyncComplete; // Session finished opening URL } SafeRelease( &pSourceUnk ); return hr; } // Get the event from the event queue. hr = m_pSession->EndGetEvent(pResult, &pEvent); CHECK_HR( hr ); // Get the event type. hr = pEvent->GetType(&meType); CHECK_HR( hr ); if (meType == MESessionClosed) { // The session was closed. // The application is waiting on the m_hCloseEvent event handle. SetEvent(m_hCloseEvent); } else { // For all other events, get the next event in the queue. hr = m_pSession->BeginGetEvent(this, NULL); CHECK_HR( hr ); } // Check the application state. // If a call to IMFMediaSession::Close is pending, it means the // application is waiting on the m_hCloseEvent event and // the application's message loop is blocked. // Otherwise, post a private window message to the application. if (m_state != Closing) { // Leave a reference count on the event. pEvent->AddRef(); PostMessage(m_hwndEvent, WM_APP_PLAYER_EVENT, (WPARAM)pEvent, (LPARAM)meType); } done: SafeRelease(&pEvent); return S_OK; }