鴨子通知的實作考慮

通訊串流開啟時,系統所提供的預設鴨子體驗 會躲避系統中所有可用的非通訊數據流。 如果媒體應用程式知道通訊會話何時開始和結束,則可以覆寫默認處理。

請考慮 DuckingMediaPlayer 範例中 媒體應用程式所實作的 案例。 應用程式會在收到鴨子通知時暫停播放的音訊串流,並在收到未擷取通知時繼續播放。 暫停和繼續事件會反映在媒體應用程式的使用者介面中。 這可透過兩個應用程式定義的視窗訊息來支援,WM_APP_SESSION_DUCKED和WM_APP_SESSION_UNDUCKED。 躲避通知會在背景以異步方式接收,媒體應用程式不得封鎖通知線程來處理視窗訊息。 視窗訊息必須在使用者介面線程上處理。

躲避行為可透過通知機制運作。 若要提供自定義體驗,媒體應用程式必須實 作IAudioVolumeDuckNotification 介面,並向音訊系統註冊實作。 成功註冊後,媒體應用程式會透過介面中的方法,以回呼的形式接收事件通知。 處理通訊會話的會話管理員會在通訊數據流開啟時呼叫 IAudioVolumeDuckNotification::OnVolumeDuckNotification,然後在通訊裝置上關閉數據流時呼叫 IAudioVolumeDuckNotification::OnVolumeUnduckNotification

下列程式代碼示範 IAudioVolumeDuckNotification 介面的範例實作 如需 CMediaPlayer::D uckingOptOut 的定義,請參閱從通訊裝置取得隱藏事件。

class CMediaPlayer : public IAudioVolumeDuckNotification
{
    LONG _refCount;

    HWND _AppWindow;

    ~CMediaPlayer();

    STDMETHOD(OnVolumeDuckNotification) (LPCWSTR sessionID, 
                  UINT32 countCommunicationSessions);
    STDMETHOD(OnVolumeUnduckNotification) (LPCWSTR sessionID);

public:
    CDuckingImpl(HWND hWnd);
    HRESULT DuckingOptOut(bool GetDuckEvents);

    // IUnknown
    IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void **ppv);
    IFACEMETHODIMP_(ULONG) AddRef();
    IFACEMETHODIMP_(ULONG) Release();
};

CMediaPlayer::CMediaPlayer(HWND AppWindow) :
        _AppWindow(AppWindow),
        _refCount(1)
{
}
CMediaPlayer::~CMediaPlayer()
{
}

// When we receive a duck notification, 
// post a "Session Ducked" message to the application window.

STDMETHODIMP CMediaPlayer::OnVolumeDuckNotification(LPCWSTR SessionID, 
                                                    UINT32 CountCommunicationsSessions)
{
    PostMessage(_AppWindow, WM_APP_SESSION_DUCKED, 0, 0);
    return 0;
}


// When we receive an unduck notification, 
// post a "Session Unducked" message to the application window.

STDMETHODIMP CMediaPlayer::OnVolumeUnduckNotification(LPCWSTR SessionID)
{
    PostMessage(_AppWindow, WM_APP_SESSION_UNDUCKED, 0, 0);
    return 0;
}

IFACEMETHODIMP CMediaPlayer::QueryInterface(REFIID iid, void **pvObject)
{
    if (pvObject == NULL)
    {
        return E_POINTER;
    }
    *pvObject = NULL;
    if (iid == IID_IUnknown)
    {
        *pvObject = static_cast<IUnknown *>(static_cast<IAudioVolumeDuckNotification *>
                                                                              (this));
        AddRef();
    }
    else if (iid == __uuidof(IAudioVolumeDuckNotification))
    {
        *pvObject = static_cast<IAudioVolumeDuckNotification *>(this);
        AddRef();
    }
    else
    {
        return E_NOINTERFACE;
    }
    return S_OK;
}

IFACEMETHODIMP_(ULONG) CMediaPlayer::AddRef()
{
    return InterlockedIncrement(&_refCount);
}

IFACEMETHODIMP_(ULONG) CMediaPlayer::Release()
{
    LONG refs = InterlockedDecrement(&_refCount);

    if (refs == 0)
    {
        delete this; 
    }

    return refs;   
}

使用通訊裝置

默認的鴨子體驗

停用預設的鴨子體驗

提供自定義的鴨子行為

取得躲避事件