Comment obtenir des événements à partir de la source réseau

Le programme de résolution de source permet à une application de créer une source réseau et d’ouvrir une connexion à une URL spécifique. La source réseau déclenche des événements pour marquer le début et la fin de l’opération asynchrone d’ouverture d’une connexion. Une application peut s’inscrire à ces événements à l’aide de l’interface IMFSourceOpenMonitor .

Cette interface expose la méthode IMFSourceOpenMonitor::OnSourceEvent que la source réseau appelle directement lorsqu’elle ouvre l’URL de manière asynchrone. La source réseau avertit l’application lorsqu’elle commence à ouvrir l’URL en déclenche l’événement MEConnectStart . La source réseau déclenche ensuite l’événement MEConnectEnd lorsqu’elle termine l’opération d’ouverture.

Notes

Pour envoyer ces événements à l’application, la source réseau n’utilise pas l’interface IMFMediaEventGenerator , car ces événements sont déclenchés avant la création de la source réseau. L’application peut obtenir tous les autres événements de source réseau à l’aide de l’interface IMFMediaEventGenerator de media Session.

 

Pour obtenir des événements à partir de la source réseau

  1. Implémentez l’interface IMFSourceOpenMonitor . Dans votre implémentation de la méthode IMFSourceOpenMonitor::OnSourceEvent , procédez comme suit :
    1. Obtenez l’événement status en appelant IMFMediaEvent::GetStatus. Cette méthode indique si l’opération qui a déclenché l’événement, telle qu’un appel de méthode de résolution source, a réussi. Si l’opération échoue, le status est un code d’échec.
    2. Traitez l’événement en fonction du type d’événement : MEConnectStart ou MEConnectEnd, que l’application peut obtenir en appelant IMFMediaEvent::GetType.
  2. Configurez une paire clé-valeur dans un objet de magasin de propriétés pour stocker un pointeur vers l’implémentation IMFSourceOpenMonitor décrite à l’étape 1.
    1. Créez un objet de magasin de propriétés en appelant la fonction PSCreateMemoryPropertyStore .
    2. Définissez la propriété MFPKEY_SourceOpenMonitor dans une structure PROPERTYKEY .
    3. Fournissez la valeur de données de type VT_UNKNOWN dans une structure PROPVARIANT en définissant le pointeur IUnknown vers l’implémentation de l’application de l’interface IMFSourceOpenMonitor .
    4. Définissez la paire clé-valeur dans le magasin de propriétés en appelant IPropertyStore::SetValue.
  3. Transmettez le pointeur du magasin de propriétés aux méthodes de programme de résolution de la source que l’application utilise pour créer la source réseau, telles que IMFSourceResolver::CreateObjectFromURL et d’autres.

Exemple

L’exemple suivant montre comment implémenter l’interface IMFSourceOpenMonitor pour obtenir des événements à partir de la source réseau.

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

L’exemple suivant montre comment définir la propriété MFPKEY_SourceOpenMonitor sur la source réseau lorsque vous ouvrez l’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;
}

Mise en réseau dans Media Foundation