Microsoft DirectX 9.0

IBroadcastEvent Interface

This topic applies to Windows XP only.

The IBroadcastEvent interface enables an object to receive events from another object without setting up a direct connection point. Applications typically do not need to use this interface.

In addition to the methods inherited from IUnknown, the IBroadcastEvent interface exposes the following method.

Method Description
Fire Fires an event.

Remarks

Broadcast events enable communication among DirectShow filters, Video Control features, and Video Control device objects. To send a broadcast event, an object calls IBroadcastEvent::Fire on the Broadcast Event Service object. Other objects can listen for events by setting up a connection point with the Broadcast Event Service object. The listener implements IBroadcastEvent and the Broadcast Event Service object calls the listener's Fire method whenever there is a new broadcast event.

Broadcast events are useful for several reasons:

The IBroadcastEvent interface is a service, which can be obtained through the Filter Graph Manager's IServiceProvider interface. To do so, call IServiceProvider::QueryService and specify the following values:

A failure code from QueryService indicates that no object has yet registered the Broadcast Event Service object with the Filter Graph Manager. In that case, do the following:

  1. Create a new Broadcast Event Service object, using CoCreateInstance.
  2. Query the Filter Graph Manager for IRegisterServiceProvider.
  3. Call IRegisterServiceProvider::RegisterService with the service identifier.

Once you have a pointer to the IBroadcastEvent interface, you can use it either to send events or to sink events. To send events, call the Fire method. To sink events, implement IBroadcastEvent on the sink object, query the Broadcast Event Service for IConnectionPoint, and call IConnectionPoint::Advise to establish the connection. For a list of defined broadcast events, see IBroadcastEvent::Fire.

Example Code

The following example implements a class that can source or sink broadcast events:

class TunerEvent : public IBroadcastEvent
{

private:
    long m_nRefCount; // Holds the reference count.
public:
    // IUnknown methods
    STDMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&m_nRefCount);
    }
    STDMETHODIMP_(ULONG) Release()
    {
        _ASSERT(m_nRefCount >= 0);
        ULONG uCount = InterlockedDecrement(&m_nRefCount);
        if (uCount == 0)
        {
            delete this;
        }
        // Return the temporary variable, not the member
        // variable, for thread safety.
        return uCount;
    }
    STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject)
    {
        if (NULL == ppvObject)
            return E_POINTER;
        if (riid == __uuidof(IUnknown))
            *ppvObject = static_cast<IUnknown*>(this);
        else if (riid == __uuidof(IBroadcastEvent))
            *ppvObject = static_cast<IBroadcastEvent*>(this);
        else 
            return E_NOINTERFACE;
        AddRef();
        return S_OK;
    }

    // The one IBroadcastEvent method
    STDMETHOD(Fire)(GUID eventID)
    {
        // The one defined event
        if (eventID == EVENTID_TuningChanged)
        {
            // The tuner changed stations or channels.
        }
        
        return S_OK;
    }

    TunerEvent() : m_dwBroadcastEventCookie(0), m_nRefCount(1) {};

private:
    HRESULT HookupGraphEventService(IFilterGraph *pGraph);
    HRESULT RegisterForTunerEvents();
    HRESULT UnRegisterForTunerEvents();
    HRESULT Fire_Event(GUID eventID);

    CComPtr<IBroadcastEvent>   m_spBroadcastEvent; 
    DWORD m_dwBroadcastEventCookie;
};

// Query the Filter Graph Manager for the broadcast event service.
// If not found, create it and register it.
HRESULT TunerEvent::HookupGraphEventService(IFilterGraph *pGraph)
{
    HRESULT hr = S_OK;
    if (!m_spBroadcastEvent)
    {
        CComQIPtr<IServiceProvider> spServiceProvider(pGraph);
        if (!spServiceProvider)
        {
            return E_NOINTERFACE;
        }
        hr = spServiceProvider->QueryService(SID_SBroadcastEventService, 
            IID_IBroadcastEvent, 
            reinterpret_cast<void**>(&m_spBroadcastEvent));
        if (FAILED(hr))
        {
            // Create the Broadcast Event Service object.
            hr = m_spBroadcastEvent.CoCreateInstance(
                CLSID_BroadcastEventService,
                NULL, CLSCTX_INPROC_SERVER);
            if (FAILED(hr))
            {
                return hr; 
            }
            
            CComQIPtr<IRegisterServiceProvider> spRegService(pGraph);
            if (!spRegService)
            {
                return E_NOINTERFACE;
            }
            
            // Register the Broadcast Event Service object as a service.
            hr = spRegService->RegisterService(
                SID_SBroadcastEventService,
                m_spBroadcastEvent);
        }
    }
    return hr;
}

// Establish the connection point to receive events.
HRESULT TunerEvent::RegisterForTunerEvents()
{
    if (!m_spBroadcastEvent)
    {
        return E_FAIL;  // Forgot to call HookupGraphEventService.
    }
    if(m_dwBroadcastEventCookie)
    {
        return S_FALSE;  // There is already a connection; nothing to do.
    }
    CComQIPtr<IConnectionPoint> spConnectionPoint(m_spBroadcastEvent);
    if(!spConnectionPoint)
    {
        return E_NOINTERFACE;
    }
    return spConnectionPoint->Advise(static_cast<IBroadcastEvent*>(this),
        &m_dwBroadcastEventCookie);
}

// Un-register for events.
HRESULT TunerEvent::UnRegisterForTunerEvents()
{
    HRESULT hr = S_OK;
    if(!m_dwBroadcastEventCookie)
    {
        return S_OK; // Not registered for events; nothing to do.
    }
    CComQIPtr<IConnectionPoint> spConnectionPoint(m_spBroadcastEvent);
    if(!spConnectionPoint)
    {
        return E_NOINTERFACE;
    }
    
    // Release the connection point.
    hr = spConnectionPoint->Unadvise(m_dwBroadcastEventCookie);
    if (FAILED(hr))
    {
        // Error: Unable to unadvise the connection point.
        return hr;
    }
    m_dwBroadcastEventCookie = 0;
    m_spBroadcastEvent.Release();
    return S_OK;
}

// Send an event (for source objects).
HRESULT TunerEvent::Fire_Event(GUID eventID)
{
    if (!m_spBroadcastEvent)
    {
        return E_FAIL; // Forgot to call HookupGraphEventService.
    }
    return m_spBroadcastEvent->Fire(eventID);
}