取得躲避事件

想要提供自定義鴨子體驗的媒體應用程式,必須在系統中開啟或關閉通訊串流時接聽事件通知。 您可以使用 MediaFoundation、DirectShow 或 DirectSound 來提供自定義實作,其使用核心音訊 API。 如果直接 WASAPI 用戶端知道通訊工作階段何時開始和結束,也可以覆寫預設處理。

若要提供自定義實作,媒體應用程式必須在通訊應用程式啟動或結束通訊數據流時,從系統取得通知。 媒體應用程式必須實 作 IAudioVolumeDuckNotification 介面,並且向音訊系統註冊實作。 成功註冊後,媒體應用程式會透過介面中的方法,以回呼的形式接收事件通知。 如需詳細資訊,請參閱 鴨子通知的實作考慮。

若要傳送躲避通知,音訊系統必須知道哪些音訊會話正在接聽鴨子事件。 每個音訊會話都會以 GUID —會話實例識別碼唯一識別。 會話管理員可讓應用程式取得會話的相關信息,例如音訊會話的標題、轉譯狀態和會話實例標識符。 您可以使用原則控制介面 IAudioSessionControl2擷取標識符。

下列步驟摘要說明取得媒體應用程式的工作階段實例識別碼的程式:

  1. 具現化裝置列舉值,並用它來取得媒體應用程式用來轉譯非通訊數據流之裝置端點的參考。
  2. 從裝置端點啟動會話管理員,並取得會話管理員 IAudioSessionManager2 介面的參考
  3. 藉由使用 IAudioSessionManager2 指標,取得會話管理員之 IAudioSessionControl 介面的參考
  4. IAudioSessionControl 介面查詢 IAudioSessionControl2
  5. 呼叫 IAudioSessionControl2::GetSessionInstanceIdentifier ,並擷取包含目前音訊會話之會話標識符的字元串。

若要取得有關通訊串流的通知,媒體應用程式會呼叫 IAudioSessionManager2::RegisterDuckNotification 媒體應用程式會將其會話實例標識碼提供給音訊系統,以及IAudioVolumeDuckNotification 實作的指標。 應用程式現在可以在通訊裝置上開啟數據流時接收事件通知。 若要停止收到通知,媒體應用程式必須呼叫 IAudioSessionManager2::UnregisterDuckNotification

下列程式代碼示範應用程式如何註冊以取得躲避通知。 CMediaPlayer 類別定義於鴨子通知的實作考慮中DuckingMediaPlayer 範例會實作這項功能。

////////////////////////////////////////////////////////////////////
//Description: Registers for duck notifications depending on the 
//             the ducking options specified by the caller.
//Parameters: 
//    If DuckingOptOutChecked is TRUE, the client is registered for
//    to receive ducking notifications; 
//    FALSE, the client's registration is deleted.
////////////////////////////////////////////////////////////////////

HRESULT CMediaPlayer::DuckingOptOut(bool DuckingOptOutChecked)
{
    HRESULT hr = S_OK;

    IMMDeviceEnumerator* pDeviceEnumerator NULL;
    IMMDevice* pEndpoint = NULL;
    IAudioSessionManager2* pSessionManager2 = NULL;
    IAudioSessionControl* pSessionControl = NULL;
    IAudioSessionControl2* pSessionControl2 = NULL;

    LPWSTR sessionId = NULL;

    //  Start with the default endpoint.

    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), 
                          NULL, 
                          CLSCTX_INPROC_SERVER, 
                          IID_PPV_ARGS(&pDeviceEnumerator));
    
    if (SUCCEEDED(hr))
    {
        hr = pDeviceEnumerator>GetDefaultAudioEndpoint(
              eRender, eConsole, &pEndpoint);

        pDeviceEnumerator>Release();
        pDeviceEnumerator = NULL;
    }

    // Activate the session manager.
    if (SUCCEEDED(hr))
    {
        hr = pEndpoint->Activate(__uuidof(IAudioSessionManager2), 
                                 CLSCTX_INPROC_SERVER,
                                 NULL, 
                                 reinterpret_cast<void **>
                                 (&pSessionManager2));
        pEndpoint->Release();
        pEndpoint = NULL;
    }
    if (SUCCEEDED(hr))
    {
        hr = pSessionManager2->GetAudioSessionControl(
                                  NULL, 0, &pSessionControl);
        
    }

    if (SUCCEEDED(hr))
    {
        hr = pSessionControl->QueryInterface(
                               IID_PPV_ARGS(&pSessionControl2));
                
        pSessionControl->Release();
        pSessionControl = NULL;
    }

    // Get the session instance identifier.
    
    if (SUCCEEDED(hr))
    {
        hr = pSessionControl2->GetSessionInstanceIdentifier(
                                 sessionId);
                
        pSessionControl2->Release();
        pSessionControl2 = NULL;
    }

    //  Register for ducking events depending on 
    //  the specified preference.

    if (SUCCEEDED(hr))
    {
        if (DuckingOptOutChecked)
        {
            hr = pSessionManager2->RegisterDuckNotification(
                                    sessionId, this);
        }
        else
        {
            hr = pSessionManager2->UnregisterDuckNotification
                                      (FALSE);
        }
        pSessionManager2->Release();
        pSessionManager2 = NULL;
    }
    return hr;
}

使用通訊裝置

默認的鴨子體驗

停用預設的鴨子體驗

提供自定義的鴨子行為

鴨子通知的實作考慮