Como obter eventos da origem da rede

O resolvedor de origem permite que um aplicativo crie uma fonte de rede e abra uma conexão com uma URL específica. A origem da rede gera eventos para marcar o início e o fim da operação assíncrona de abertura de uma conexão. Um aplicativo pode se registrar para esses eventos usando a interface IMFSourceOpenMonitor .

Essa interface expõe o método IMFSourceOpenMonitor::OnSourceEvent que a fonte de rede chama diretamente quando abre a URL de forma assíncrona. A fonte de rede notifica o aplicativo quando ele começa a abrir a URL acionando o evento MEConnectStart . Em seguida, a fonte de rede aciona o evento MEConnectEnd quando conclui a operação aberta.

Observação

Para enviar esses eventos para o aplicativo, a fonte de rede não usa a interface IMFMediaEventGenerator porque esses eventos são gerados antes da criação da fonte de rede. O aplicativo pode obter todos os outros eventos de origem de rede usando a interface IMFMediaEventGenerator da Sessão de Mídia.

 

Para obter eventos da origem da rede

  1. Implemente a interface IMFSourceOpenMonitor . Na implementação do método IMFSourceOpenMonitor::OnSourceEvent , faça o seguinte:
    1. Obtenha o evento status chamando IMFMediaEvent::GetStatus. Esse método indica se a operação que disparou o evento, como uma chamada de método de resolvedor de origem, foi bem-sucedida. Se a operação não for bem-sucedida, o status será um código de falha.
    2. Processe o evento com base no tipo de evento: MEConnectStart ou MEConnectEnd, que o aplicativo pode obter chamando IMFMediaEvent::GetType.
  2. Configure um par chave-valor em um objeto de repositório de propriedades para armazenar um ponteiro para a implementação IMFSourceOpenMonitor descrita na etapa 1.
    1. Crie um objeto de repositório de propriedades chamando a função PSCreateMemoryPropertyStore .
    2. Defina a propriedade MFPKEY_SourceOpenMonitor em uma estrutura PROPERTYKEY .
    3. Forneça o valor de dados de tipo VT_UNKNOWN em uma estrutura PROPVARIANT definindo o ponteiro IUnknown para a implementação do aplicativo da interface IMFSourceOpenMonitor .
    4. Defina o par chave-valor no repositório de propriedades chamando IPropertyStore::SetValue.
  3. Passe o ponteiro do repositório de propriedades para os métodos de resolvedor de origem que o aplicativo está usando para criar a fonte de rede, como IMFSourceResolver::CreateObjectFromURL e outros.

Exemplo

O exemplo a seguir mostra como implementar a interface IMFSourceOpenMonitor para obter eventos da origem da rede.

class CSourceOpenMonitor : public IMFSourceOpenMonitor
{
public:
    CSourceOpenMonitor () : m_cRef(1) { }

    STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
    {
        static const QITAB qit[] = 
        {
            QITABENT(CSourceOpenMonitor, IMFSourceOpenMonitor),
            { 0 }
        };
        return QISearch(this, qit, riid, ppv);
    }

    STDMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&m_cRef);
    }

    STDMETHODIMP_(ULONG) Release()
    {
        LONG cRef = InterlockedDecrement(&m_cRef);
        if (cRef == 0)
        {
            delete this;
        }
        // For thread safety, return a temporary variable.
        return cRef;
    }


    STDMETHODIMP OnSourceEvent(IMFMediaEvent* pEvent)
    {
        MediaEventType eventType = MEUnknown;   // Event type
        HRESULT hrStatus = S_OK;                // Event status

        // Get the event type.
        HRESULT hr = pEvent->GetType(&eventType);

        // Get the event status. If the operation that triggered the event
        // did not succeed, the status is a failure code.
        if (SUCCEEDED(hr))
        {
            hr = pEvent->GetStatus(&hrStatus);
        }

        if (FAILED(hrStatus))
        {
            hr = hrStatus;
        }

        if (SUCCEEDED(hr))
        {
            // Switch on the event type.
            switch(eventType)
            {
                case MEConnectStart:
                    // The application does something. (Not shown.)
                    OutputDebugString(L"Connecting...\n");
                    break;

                case MEConnectEnd:
                    // The application does something. (Not shown.)
                    OutputDebugString(L"Connect End.\n");
                    break;
            }
        }
        else
        {
            // Event failed.
            // The application handled a failure. (Not shown.)
        }
        return S_OK;
    }
private:
    long    m_cRef;
};

O exemplo a seguir mostra como definir a propriedade MFPKEY_SourceOpenMonitor na fonte de rede quando você abre a URL:

HRESULT CreateMediaSourceWithSourceOpenMonitor(
    PCWSTR pszURL, 
    IMFMediaSource **ppSource
    )
{
    IPropertyStore *pConfig = NULL;

    CSourceOpenMonitor *pMonitor = new (std::nothrow) CSourceOpenMonitor();

    if (pMonitor == NULL)
    {
        return E_OUTOFMEMORY;
    }

    // Configure the property store.
    HRESULT hr = PSCreateMemoryPropertyStore(IID_PPV_ARGS(&pConfig));

    if (SUCCEEDED(hr))
    {
        PROPVARIANT var;
        var.vt = VT_UNKNOWN;
        pMonitor->QueryInterface(IID_PPV_ARGS(&var.punkVal));

        hr = pConfig->SetValue(MFPKEY_SourceOpenMonitor, var);

        PropVariantClear(&var);
    }

    // Create the source media source.
    if (SUCCEEDED(hr))
    {
        hr = CreateMediaSource(pszURL, pConfig, ppSource);
    }

    SafeRelease(&pConfig);
    SafeRelease(&pMonitor);

    return hr;
}

Networking in Media Foundation