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;
}