Beispiel #1
0
// ----------------------------------------------------------------------
// Function:
//      CPartsList::AddPart
//
// Description: 
//      Adds the PartsList Parts to the list of IPart interfaces
//
// Parameters:
//      pIParts - [in] List of Parts to be added to the list
//
// Return:
//      S_OK if successful
// ----------------------------------------------------------------------
STDMETHODIMP CPartsList::AddParts
(
    IPartsList* pIParts
)
{
    ATLASSERT(pIParts != NULL);

    HRESULT hr = S_OK;
    UINT i, cParts = 0;

    // Protect m_lstParts
    m_CritSection.Enter();

    // Loop through specified parts list
    hr = pIParts->GetCount(&cParts);
    IF_FAILED_JUMP(hr, Exit);

    for (i = 0; (i < cParts) && (hr == S_OK); i++)
    {
        IPart*  pIPart;

        // ... and copy reference to each part
        hr = pIParts->GetPart(i, &pIPart);
        IF_FAILED_JUMP(hr, Exit);

        // ... to this list
        m_lstParts.AddTail(pIPart);
    }

Exit:
    m_CritSection.Leave();

    return hr;
}
///////////////////////////////////////////////////////////////////////////////
// Function:
//      GetJackSubtypeForEndpoint
//
// Description:
//      Gets the subtype of the jack that the specified endpoint device
//      is plugged into.  e.g. if the endpoint is for an array mic, then
//      we would expect the subtype of the jack to be 
//      KSNODETYPE_MICROPHONE_ARRAY
//
// Return:
//      S_OK if successful
//
///////////////////////////////////////////////////////////////////////////////
HRESULT GetJackSubtypeForEndpoint(IMMDevice* pEndpoint, GUID* pgSubtype)
{
    HRESULT hr = S_OK;

    if (pEndpoint == NULL)
        return E_POINTER;
   
    CComPtr<IDeviceTopology>    spEndpointTopology;
    CComPtr<IConnector>         spPlug;
    CComPtr<IConnector>         spJack;
    CComQIPtr<IPart>            spJackAsPart;

    // Get the Device Topology interface
    hr = pEndpoint->Activate(__uuidof(IDeviceTopology), CLSCTX_INPROC_SERVER, 
                            NULL, (void**)&spEndpointTopology);
    IF_FAILED_JUMP(hr, Exit);

    hr = spEndpointTopology->GetConnector(0, &spPlug);
    IF_FAILED_JUMP(hr, Exit);

    hr = spPlug->GetConnectedTo(&spJack);
    IF_FAILED_JUMP(hr, Exit);

    spJackAsPart = spJack;

    hr = spJackAsPart->GetSubType(pgSubtype);

Exit:
   return hr;
}//GetJackSubtypeForEndpoint()
// ----------------------------------------------------------------------------
// Function:
//      CSwapPropPage::SetDelayMFXState
//
// Description:
//      Enable or disable delay MFX
//
// Return values:
//      S_OK if successful
// ----------------------------------------------------------------------------
HRESULT CSwapPropPage::SetDelayMFXState()
{
    BOOL fCurrentState = 0;
    HRESULT hr = RetrieveDelayMFXState(&fCurrentState);
    IF_FAILED_JUMP(hr, Exit);

    if (fCurrentState != m_fEnableDelayMFX)
    {
        PROPVARIANT var;
        var.vt = VT_UI4;
        var.ulVal = (m_fEnableDelayMFX ? 1L : 0L);

        // Enable or disable delay MFX
        hr = m_pAudioFXExtParams->pFxProperties->SetValue(PKEY_Endpoint_Enable_Delay_MFX, var);
        IF_FAILED_JUMP(hr, Exit);
        
        // Enabling or disabling delay changes the value that should be returned by IAudioProcessingObject::GetLatency
        // This is one of the things that is locked by IAudioProcessingObjectConfiguration::LockForProcess
        // So we need to call IAudioEndpointFormatControl::ResetToDefault
        // This will prompt AudioDG to tear down the graph and build it up again
        m_fReset = TRUE;
    }

Exit:
    return(hr);
}
Beispiel #4
0
// ----------------------------------------------------------------------------
// Function:
//      CSwapPropPage::OnApply
//
// Description:
//      Handle the pressing of the apply button
//
// Parameters:
//      hwndDlg - [in] Handle to the dialog box
//
// Return values:
//      TRUE to set keyboard focus on control
// ----------------------------------------------------------------------------
BOOL CSwapPropPage::OnApply
(
    HWND hwndDlg
)
{
    HRESULT hr = S_OK;

    // Commit the settings
    hr = SetSysFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetSwapLFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetSwapGFXState();
    IF_FAILED_JUMP(hr, Exit);

Exit:
    if (SUCCEEDED(hr))
    {
        SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
    }
    else
    {
        SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID);
    }

    return(TRUE);
}
Beispiel #5
0
HRESULT CSwapAPOLFX::Initialize(UINT32 cbDataSize, BYTE* pbyData)
{
    HRESULT                         hr = S_OK;
    PROPVARIANT                     var;

    IF_TRUE_ACTION_JUMP( ((NULL == pbyData) && (0 != cbDataSize)), hr = E_INVALIDARG, Exit);
    IF_TRUE_ACTION_JUMP( ((NULL != pbyData) && (0 == cbDataSize)), hr = E_POINTER, Exit);
    IF_TRUE_ACTION_JUMP( (cbDataSize != sizeof(APOInitSystemEffects) ), hr = E_INVALIDARG, Exit);

    APOInitSystemEffects* papoSysFxInit = (APOInitSystemEffects*)pbyData;

    //
    //  Store locally for later reference
    //
    m_spAPOSystemEffectsProperties = papoSysFxInit->pAPOSystemEffectsProperties;

    //
    //  Get the current value
    //
    PropVariantInit(&var);

    if (m_spAPOSystemEffectsProperties != NULL)
    {
        // Get the state of whether channel swap LFX is enabled or not
        hr = m_spAPOSystemEffectsProperties->GetValue(PKEY_Endpoint_Enable_Channel_Swap_LFX, &var);

        if (SUCCEEDED(hr) && (var.vt == VT_UI4))
        {
            if (var.ulVal == 0L)
            {
                m_fEnableSwapLFX = FALSE;
            }
            else
            {
                m_fEnableSwapLFX = TRUE;
            }
        }
        else
        {
            PropVariantClear(&var);
        }
    }

    //
    //  Register for notification of registry updates
    //
    hr = m_spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hr, Exit);

    hr = m_spEnumerator->RegisterEndpointNotificationCallback(this);
    IF_FAILED_JUMP(hr, Exit);

     m_bIsInitialized = true;


Exit:
    return hr;
}
Beispiel #6
0
//-------------------------------------------------------------------------
// Description:
//
//  Validates input/output format pair during LockForProcess.
//
// Parameters:
//
//      u32NumInputConnections - [in] number of input connections attached to this APO
//      ppInputConnections - [in] format of each input connection attached to this APO
//      u32NumOutputConnections - [in] number of output connections attached to this APO
//      ppOutputConnections - [in] format of each output connection attached to this APO
//
// Return values:
//
//      S_OK                                Connections are valid.
//
// See Also:
//
//  CBaseAudioProcessingObject::LockForProcess
//
// Remarks:
//
//  This method is an internal call that is called by the default implementation of
//  CBaseAudioProcessingObject::LockForProcess().  This is called after the connections
//  are validated for simple conformance to the APO's registration properties.  It may be
//  used to verify that the APO is initialized properly and that the connections that are passed
//  agree with the data used for initialization.  Any failure code passed back from this
//  function will get returned by LockForProcess, and cause it to fail.
//
//  By default, this routine just ASSERTS and returns S_OK.
//
HRESULT CSwapAPOGFX::ValidateAndCacheConnectionInfo(UINT32 u32NumInputConnections,
                APO_CONNECTION_DESCRIPTOR** ppInputConnections,
                UINT32 u32NumOutputConnections,
                APO_CONNECTION_DESCRIPTOR** ppOutputConnections)
{
    ASSERT_NONREALTIME();
    HRESULT hResult;
    CComPtr<IAudioMediaType> pFormat;
    UNCOMPRESSEDAUDIOFORMAT UncompInputFormat, UncompOutputFormat;
    FLOAT32 f32InverseChannelCount;

    UNREFERENCED_PARAMETER(u32NumInputConnections);
    UNREFERENCED_PARAMETER(u32NumOutputConnections);

    _ASSERTE(!m_bIsLocked);
    _ASSERTE(((0 == u32NumInputConnections) || (NULL != ppInputConnections)) &&
              ((0 == u32NumOutputConnections) || (NULL != ppOutputConnections)));

    EnterCriticalSection(&m_CritSec);

    // get the uncompressed formats and channel masks
    hResult = ppInputConnections[0]->pFormat->GetUncompressedAudioFormat(&UncompInputFormat);
    IF_FAILED_JUMP(hResult, Exit);
    
    hResult = ppOutputConnections[0]->pFormat->GetUncompressedAudioFormat(&UncompOutputFormat);
    IF_FAILED_JUMP(hResult, Exit);

    // Since we haven't overridden the IsIn{Out}putFormatSupported APIs in this example, this APO should
    // always have input channel count == output channel count.  The sampling rates should also be eqaul,
    // and formats 32-bit float.
    _ASSERTE(UncompOutputFormat.fFramesPerSecond == UncompInputFormat.fFramesPerSecond);
    _ASSERTE(UncompOutputFormat. dwSamplesPerFrame == UncompInputFormat.dwSamplesPerFrame);

    // Allocate some locked memory.  We will use these as scaling coefficients during APOProcess->ProcessSwapScale
    hResult = AERT_Allocate(sizeof(FLOAT32)*m_u32SamplesPerFrame, (void**)&m_pf32Coefficients);
    IF_FAILED_JUMP(hResult, Exit);

    // Set scalars to decrease volume from 1.0 to 1.0/N where N is the number of channels
    // starting with the first channel.
    f32InverseChannelCount = 1.0f/m_u32SamplesPerFrame;
    for (UINT16 u16Index=0; u16Index<m_u32SamplesPerFrame; u16Index++)
    {
        m_pf32Coefficients[u16Index] = 1.0f - (FLOAT32)(f32InverseChannelCount)*u16Index;
    }

    
Exit:
    LeaveCriticalSection(&m_CritSec);
    return hResult;}
Beispiel #7
0
// ----------------------------------------------------------------------
// Function:
//      CPartsList::GetPart
//
// Description:
//      Returns the nIndex-th item in the list of IParts
//
// Parameters:
//      nIndex - [in] index of the part to access
//      uMsg - [out] the part at the specified index
//
// Return:
//      S_OK if successful
//
// ----------------------------------------------------------------------
_Use_decl_annotations_
STDMETHODIMP CPartsList::GetPart
(
    UINT nIndex,
    IPart** ppPart
)
{
    HRESULT hr;
    IPart*  pIPart = NULL;

    // Protect m_lstParts access
    m_CritSection.Enter();

    IF_TRUE_ACTION_JUMP((ppPart == NULL), hr = E_POINTER, Exit);

    *ppPart = NULL;

    IF_TRUE_ACTION_JUMP((nIndex >= m_lstParts.GetCount()), hr = E_INVALIDARG, Exit);

    IF_TRUE_ACTION_JUMP((!m_lstParts.GetAt(nIndex, &pIPart)), hr = E_NOTFOUND, Exit);

    // Take care of AddRef and ensure correct interface in one shot
    hr = pIPart->QueryInterface(__uuidof(IPart), reinterpret_cast<void**>(ppPart));
    IF_FAILED_JUMP(hr, Exit);

Exit:
    m_CritSection.Leave();

    return hr;
}
Beispiel #8
0
NTSTATUS CMiniportWaveRTStream::GetPosition
(
    _Out_   KSAUDIO_POSITION    *Position_
)
{
    NTSTATUS ntStatus;

#ifdef SYSVAD_BTH_BYPASS
    if (m_ScoOpen)
    {
        ntStatus = GetScoStreamNtStatus();
        IF_FAILED_JUMP(ntStatus, Done);
    }
#endif // SYSVAD_BTH_BYPASS

    if (m_KsState == KSSTATE_RUN)
    {
        //
        // Get the current time and update position.
        //
        LARGE_INTEGER ilQPC = KeQueryPerformanceCounter(NULL);
        UpdatePosition(ilQPC);
    }

    Position_->PlayOffset = m_ullPlayPosition;
    Position_->WriteOffset = m_ullWritePosition;

    ntStatus = STATUS_SUCCESS;
    
#ifdef SYSVAD_BTH_BYPASS
Done:
#endif // SYSVAD_BTH_BYPASS
    return ntStatus;
}
///////////////////////////////////////////////////////////////////////////
//
// Function:
//      DeviceBindTo
//
// Description:
//      Bind device to an IAudioClient interface.
//
//  Parameters:
//      eDataFlow: eRender for render device, eCapture for capture device
//      iDevIdx: Index of device in the enumeration list. If it is -1, use default device 
//      ppVoid: pointer pointer to IAudioClient interface.
//      ppszEndpointDeviceId: Device ID. Caller is responsible for freeing memeory
//              using CoTaskMemoryFree. If can be NULL if called doesn't need this info.
//
// Return:
//      S_OK if successful
//
///////////////////////////////////////////////////////////////////////////////
HRESULT DeviceBindTo(
        EDataFlow eDataFlow,    // eCapture/eRender
        INT iDevIdx,        // Device Index. -1 - default device. 
        IAudioClient **ppAudioClient,    // pointer pointer to IAudioClient interface
        IAudioEndpointVolume **ppEndpointVolume,
        WCHAR** ppszEndpointDeviceId)   // Device ID. Need to be freed in caller with CoTaskMemoryFree if it is not NULL
{
    HRESULT hResult;

    CComPtr<IMMDeviceEnumerator> spEnumerator;
    CComPtr<IMMDeviceCollection> spEndpoints;    
    CComPtr<IMMDevice> spDevice;
    WCHAR *pszDeviceId = NULL;

    if (ppAudioClient == NULL) 
        return E_POINTER;
    
    *ppAudioClient = NULL;

    hResult = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hResult, Exit);

    // use default device
    if (iDevIdx < 0 )
    {
        hResult = spEnumerator->GetDefaultAudioEndpoint(eDataFlow, eConsole, &spDevice);
        IF_FAILED_JUMP(hResult, Exit);
    }else{
        // User selected device
        hResult = spEnumerator->EnumAudioEndpoints(eDataFlow, DEVICE_STATE_ACTIVE, &spEndpoints);
        IF_FAILED_JUMP(hResult, Exit);

        hResult = spEndpoints->Item(iDevIdx, &spDevice);
        IF_FAILED_JUMP(hResult, Exit);
    }

    // get device ID and format
    hResult = spDevice->GetId(&pszDeviceId);
    IF_FAILED_JUMP(hResult, Exit);

    // Active device
    hResult = spDevice->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)ppAudioClient);
    IF_FAILED_JUMP(hResult, Exit);

    if (ppEndpointVolume)
    {
        hResult = spDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (void **)ppEndpointVolume);
        IF_FAILED_JUMP(hResult, Exit);
    }
    
Exit:
    if (ppszEndpointDeviceId)
        *ppszEndpointDeviceId = pszDeviceId;
    else if (pszDeviceId)
        CoTaskMemFree(pszDeviceId);
    
    return hResult;
}
///////////////////////////////////////////////////////////////////////////
//
// Function:
//      EnumDevice
//
// Description:
//      Enumerate audio device and return the device information.
//
//  Parameters:
//      eDataFlow: eRender for render device, eCapture for capture device
//      uNumElements: Size of audio device info structure array.
//      pDevicInfo: device info structure array. Caller is responsible to allocate and free
//                  memory. The array size is specified by uNumElements.
//
// Return:
//      S_OK if successful
//
///////////////////////////////////////////////////////////////////////////////
HRESULT EnumDevice(EDataFlow eDataFlow, UINT uNumElements, AUDIO_DEVICE_INFO *pDevicInfo)
{
    HRESULT hResult = S_OK;
    WCHAR* pszDeviceId = NULL;
    PROPVARIANT value;
    UINT index, dwCount;
    bool IsMicArrayDevice;

    CComPtr<IMMDeviceEnumerator> spEnumerator;
    CComPtr<IMMDeviceCollection> spEndpoints;    

    hResult = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hResult, Exit);

    hResult = spEnumerator->EnumAudioEndpoints(eDataFlow, DEVICE_STATE_ACTIVE, &spEndpoints);
    IF_FAILED_JUMP(hResult, Exit);

    hResult = spEndpoints->GetCount(&dwCount);
    IF_FAILED_JUMP(hResult, Exit);

    if (dwCount != uNumElements)
        return E_INVALIDARG;

    ZeroMemory(pDevicInfo, sizeof(AUDIO_DEVICE_INFO)*uNumElements);
    
    for (index = 0; index < dwCount; index++)
    {
        CComPtr<IMMDevice> spDevice;
        CComPtr<IPropertyStore> spProperties;

        PropVariantInit(&value);

        hResult = spEndpoints->Item(index, &spDevice);
        IF_FAILED_JUMP(hResult, Exit);
         
        hResult = spDevice->GetId(&pszDeviceId);
        IF_FAILED_JUMP(hResult, Exit);

        hResult = spDevice->OpenPropertyStore(STGM_READ, &spProperties);
        IF_FAILED_JUMP(hResult, Exit);

        hResult = spProperties->GetValue(PKEY_Device_FriendlyName, &value);
        IF_FAILED_JUMP(hResult, Exit);

        EndpointIsMicArray(spDevice, IsMicArrayDevice);

        StringCchCopy(pDevicInfo[index].szDeviceID, MAX_STR_LEN-1, pszDeviceId);
        StringCchCopy(pDevicInfo[index].szDeviceName, MAX_STR_LEN-1, value.pwszVal);
        pDevicInfo[index].bIsMicArrayDevice = IsMicArrayDevice;
        
        PropVariantClear(&value);
        CoTaskMemFree(pszDeviceId);
        pszDeviceId = NULL;
    }

Exit:
    return hResult;
}
// ----------------------------------------------------------------------------
// Function:
//      CSwapPropPage::GetDeviceFriendlyName
//
// Description:
//      Retrieves the endpoint's friendly name
//
// Parameters:
//      ppNameOut - [out] The friendly name of the endpoint
//
// Return values:
//      S_OK if successful
// ----------------------------------------------------------------------------
HRESULT CSwapPropPage::GetDeviceFriendlyName
(
    _Outptr_result_maybenull_ LPWSTR* ppNameOut
)
{
    CComPtr<IMMDeviceEnumerator>    spEnumerator;
    CComPtr<IPropertyStore>         spProperties;
    CComPtr<IMMDevice>              spMMDevice;
    HRESULT                         hr = S_OK;
    PROPVARIANT                     var;

    IF_TRUE_ACTION_JUMP((ppNameOut == NULL), hr = E_POINTER, Exit);

    *ppNameOut = NULL;

    // Create device enumerator and get IMMDevice from the device ID
    hr = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hr, Exit);

    hr = spEnumerator->GetDevice(m_pAudioFXExtParams->pwstrEndpointID, &spMMDevice);
    IF_FAILED_JUMP(hr, Exit);

    // Open the PropertyStore for read access
    hr = spMMDevice->OpenPropertyStore(STGM_READ, &spProperties);
    IF_FAILED_JUMP(hr, Exit);

    PropVariantInit(&var);

    // Retrieve the friendly name of the endpoint
    hr = spProperties->GetValue(PKEY_Device_FriendlyName, &var);
    if (SUCCEEDED(hr) && (var.vt == VT_LPWSTR))
    {
        *ppNameOut = var.pwszVal;
    }
    else
    {
        PropVariantClear(&var);
    }

Exit:
    return(hr);
}
// ----------------------------------------------------------------------------
// Function:
//      CSwapPropPage::SetSysFXState
//
// Description:
//      Enable or disable system effects
//
// Return values:
//      S_OK if successful
// ----------------------------------------------------------------------------
HRESULT CSwapPropPage::SetSysFXState()
{
    BOOL fCurrentState = 0;
    HRESULT hr = RetrieveSysFXState(&fCurrentState);
    IF_FAILED_JUMP(hr, Exit);

    if (fCurrentState != m_fDisableSysFX)
    {
        PROPVARIANT var;
        var.vt = VT_UI4;
        var.ulVal = (m_fDisableSysFX ? 1L : 0L);

        // Enable or disable SysFX
        hr = m_pAudioFXExtParams->pFxProperties->SetValue(PKEY_AudioEndpoint_Disable_SysFx, var);
    }
    
Exit:
    return(hr);
}
Beispiel #13
0
NTSTATUS 
InstallAllRenderFilters(
    _In_ PDEVICE_OBJECT DeviceObject, 
    _In_ PIRP           Irp, 
    _In_ PADAPTERCOMMON AdapterCommon
    )
{
    PAGED_CODE();

    NTSTATUS            ntStatus;
    PENDPOINT_MINIPAIR* ppMiniportPair   = g_RenderEndpoints;
    
    for(ULONG i = 0; i < g_cRenderEndpoints; ++i, ++ppMiniportPair)
    {
        ntStatus = InstallEndpointRenderFilters(DeviceObject, Irp, AdapterCommon, *ppMiniportPair);
        IF_FAILED_JUMP(ntStatus, Exit);
    }
    
    ntStatus = STATUS_SUCCESS;

Exit:
    return ntStatus;
}
//-------------------------------------------------------------------------
// Description:
//
//  Verifies that the APO is ready to process and locks its state if so.
//
// Parameters:
//
//      u32NumInputConnections - [in] number of input connections attached to this APO
//      ppInputConnections - [in] connection descriptor of each input connection attached to this APO
//      u32NumOutputConnections - [in] number of output connections attached to this APO
//      ppOutputConnections - [in] connection descriptor of each output connection attached to this APO
//
// Return values:
//
//      S_OK                                Object is locked and ready to process.
//      E_POINTER                           Invalid pointer passed to function.
//      APOERR_INVALID_CONNECTION_FORMAT    Invalid connection format.
//      APOERR_NUM_CONNECTIONS_INVALID      Number of input or output connections is not valid on
//                                          this APO.
STDMETHODIMP CSwapAPOMFX::LockForProcess(UINT32 u32NumInputConnections,
    APO_CONNECTION_DESCRIPTOR** ppInputConnections,  
    UINT32 u32NumOutputConnections, APO_CONNECTION_DESCRIPTOR** ppOutputConnections)
{
    ASSERT_NONREALTIME();
    HRESULT hr = S_OK;
    
    hr = CBaseAudioProcessingObject::LockForProcess(u32NumInputConnections,
        ppInputConnections, u32NumOutputConnections, ppOutputConnections);
    IF_FAILED_JUMP(hr, Exit);
    
    if (!IsEqualGUID(m_AudioProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) && m_fEnableDelayMFX)
    {
        m_nDelayFrames = FRAMES_FROM_HNS(HNS_DELAY);
        m_iDelayIndex = 0;

        m_pf32DelayBuffer.Free();

        // Allocate one second's worth of audio
        // 
        // This allocation is being done using CoTaskMemAlloc because the delay is very large
        // This introduces a risk of glitches if the delay buffer gets paged out
        //
        // A more typical approach would be to allocate the memory using AERT_Allocate, which locks the memory
        // But for the purposes of this APO, CoTaskMemAlloc suffices, and the risk of glitches is not important
        m_pf32DelayBuffer.Allocate(GetSamplesPerFrame() * m_nDelayFrames);
        WriteSilence(m_pf32DelayBuffer, m_nDelayFrames, GetSamplesPerFrame());
        if (nullptr == m_pf32DelayBuffer)
        {
            hr = E_OUTOFMEMORY;
            goto Exit;
        }
    }
    
Exit:
    return hr;
}
// ----------------------------------------------------------------------------
// Function:
//      CSwapPropPage::SetSwapMFXState
//
// Description:
//      Enable or disable channel swap MFX
//
// Return values:
//      S_OK if successful
// ----------------------------------------------------------------------------
HRESULT CSwapPropPage::SetSwapMFXState()
{
    BOOL fCurrentState = 0;
    HRESULT hr = RetrieveSwapMFXState(&fCurrentState);
    IF_FAILED_JUMP(hr, Exit);

    if (fCurrentState != m_fEnableSwapMFX)
    {
        PROPVARIANT var;
        var.vt = VT_UI4;
        var.ulVal = (m_fEnableSwapMFX ? 1L : 0L);

        // Enable or disable channel swap MFX
        hr = m_pAudioFXExtParams->pFxProperties->SetValue(PKEY_Endpoint_Enable_Channel_Swap_MFX, var);

        // Enabling or disabling the swap effect can be done with the engine running
        // It does not invalidate anything which should be locked by IAudioProcessingObjectConfiguration::LockForProcess
        // In particular, it does not impact IAudioProcessingObject::GetLatency
        // So we do not need to call IAudioEndpointFormatControl::ResetToDefault here
    }

Exit:
    return(hr);
}
Beispiel #16
0
HRESULT CSwapAPOGFX::Initialize(UINT32 cbDataSize, BYTE* pbyData)
{
    HRESULT		        hr = S_OK;
    GUID                        processingMode;

    IF_TRUE_ACTION_JUMP( ((NULL == pbyData) && (0 != cbDataSize)), hr = E_INVALIDARG, Exit);
    IF_TRUE_ACTION_JUMP( ((NULL != pbyData) && (0 == cbDataSize)), hr = E_INVALIDARG, Exit);

    if (cbDataSize == sizeof(APOInitSystemEffects2))
    {
        //
        // Initialize for mode-specific signal processing
        //
        APOInitSystemEffects2* papoSysFxInit2 = (APOInitSystemEffects2*)pbyData;

        // Save reference to the effects property store. This saves effects settings
        // and is the communication medium between this APO and any associated UI.
        m_spAPOSystemEffectsProperties = papoSysFxInit2->pAPOSystemEffectsProperties;

        // Windows should pass a valid collection.
        ATLASSERT(papoSysFxInit2->pDeviceCollection != nullptr);
        IF_TRUE_ACTION_JUMP(papoSysFxInit2->pDeviceCollection == nullptr, hr = E_INVALIDARG, Exit);

        // Save the processing mode being initialized.
        processingMode = papoSysFxInit2->AudioProcessingMode;

        // There is information in the APOInitSystemEffects2 structure that could help facilitate 
        // proprietary communication between an APO instance and the KS pin that the APO is initialized on
        // Eg, in the case that an APO is implemented as an effect proxy for the effect processing hosted inside
        // an driver (either host CPU based or offload DSP based), the example below uses a combination of 
        // IDeviceTopology, IConnector, and IKsControl interfaces to communicate with the underlying audio driver. 
        // the following following routine demonstrates how to implement how to communicate to an audio driver from a APO.
        ProprietaryCommunicationWithDriver(papoSysFxInit2);
    }
    else if (cbDataSize == sizeof(APOInitSystemEffects))
    {
        //
        // Initialize for default signal processing
        //
        APOInitSystemEffects* papoSysFxInit = (APOInitSystemEffects*)pbyData;

        // Save reference to the effects property store. This saves effects settings
        // and is the communication medium between this APO and any associated UI.
        m_spAPOSystemEffectsProperties = papoSysFxInit->pAPOSystemEffectsProperties;

        // Assume default processing mode
        processingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
    }
    else
    {
        // Invalid initialization size
        hr = E_INVALIDARG;
        goto Exit;
    }

    // Validate then save the processing mode. Note an endpoint effects APO
    // does not depend on the mode. Windows sets the APOInitSystemEffects2
    // AudioProcessingMode member to GUID_NULL for an endpoint effects APO.
    IF_TRUE_ACTION_JUMP( (processingMode != AUDIO_SIGNALPROCESSINGMODE_DEFAULT && processingMode != AUDIO_SIGNALPROCESSINGMODE_RAW), hr = E_INVALIDARG, Exit);
    m_AudioProcessingMode = processingMode;

    //
    // An APO that implements signal processing more complex than this sample
    // would configure its processing for the processingMode determined above.
    // If necessary, the APO would also use the IDeviceTopology and IConnector
    // interfaces retrieved above to communicate with its counterpart audio
    // driver to configure any additional signal processing in the driver and
    // associated hardware.
    //

    //
    //  Get current effects settings
    //
    if (m_spAPOSystemEffectsProperties != NULL)
    {
        m_fEnableSwapGFX = GetCurrentEffectsSetting(m_spAPOSystemEffectsProperties, PKEY_Endpoint_Enable_Channel_Swap_GFX, m_AudioProcessingMode);
    }

    //
    //  Register for notification of registry updates
    //
    hr = m_spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hr, Exit);

    hr = m_spEnumerator->RegisterEndpointNotificationCallback(this);
    IF_FAILED_JUMP(hr, Exit);

    m_bIsInitialized = true;
Exit:
    return hr;
}
// ----------------------------------------------------------------------------
// Function:
//      CSwapPropPage::OnApply
//
// Description:
//      Handle the pressing of the apply button
//
// Parameters:
//      hwndDlg - [in] Handle to the dialog box
//
// Return values:
//      TRUE to set keyboard focus on control
// ----------------------------------------------------------------------------
BOOL CSwapPropPage::OnApply
(
    HWND hwndDlg
)
{
    HRESULT hr = S_OK;

    // Commit the settings
    hr = SetSysFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetSwapSFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetSwapMFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetDelaySFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetDelayMFXState();
    IF_FAILED_JUMP(hr, Exit);
    
    if (NULL != m_pAudioFXExtParams && NULL != m_pAudioFXExtParams->pFxProperties)
    {
        hr = m_pAudioFXExtParams->pFxProperties->Commit();
        IF_FAILED_JUMP(hr, Exit);

        if (m_fReset)
        {
            // something changed that forces us to reset the format support
            CComPtr<IMMDeviceEnumerator>    spEnumerator;
            CComPtr<IMMDevice>              spMMDevice;

            // Create device enumerator and get IMMDevice from the device ID
            hr = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
            IF_FAILED_JUMP(hr, Exit);

            hr = spEnumerator->GetDevice(m_pAudioFXExtParams->pwstrEndpointID, &spMMDevice);
            IF_FAILED_JUMP(hr, Exit);

            CComPtr<IAudioEndpointFormatControl> spEndpointFormat;  
            hr = spMMDevice->Activate(__uuidof(IAudioEndpointFormatControl), CLSCTX_ALL, NULL, (void **)&spEndpointFormat);
            IF_FAILED_JUMP(hr, Exit);

            spEndpointFormat->ResetToDefault(ENDPOINT_FORMAT_RESET_MIX_ONLY);
            m_fReset = FALSE;
        }
    }
    
Exit:
    if (SUCCEEDED(hr))
    {
        SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
    }
    else
    {
        SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID);
    }

    return(TRUE);
}
// ----------------------------------------------------------------------------
// Function:
//      CSwapPropPage::OnInitDialog
//
// Description:
//      Dialog initialization routine
//
// Parameters:
//      hwndDlg - [in] Handle to dialog box
//      wParam - [in] Handle to control to receive the default keyboard focus
//      lParam - [in] Specifies additional message-specific information
//
// Return values:
//      TRUE to direct the system to set the keyboard focus to the control
//      specified by wParam. Otherwise, it should return FALSE to prevent the
//      system from setting the default keyboard focus.
// ----------------------------------------------------------------------------
BOOL CSwapPropPage::OnInitDialog
(
    HWND hwndDlg,
    WPARAM wParam,
    LPARAM lParam
)
{
    UNREFERENCED_PARAMETER(wParam);
    UNREFERENCED_PARAMETER(lParam);

    HRESULT hr = S_OK;
    LPWSTR pwstrEndpointName = NULL;

    // Retrieve the endpoint's friendly name, system effects, and swap SFX and MFX states
    hr = GetDeviceFriendlyName(&pwstrEndpointName);
    IF_FAILED_JUMP(hr, Exit);

    hr = RetrieveSysFXState(&m_fDisableSysFX);
    IF_FAILED_JUMP(hr, Exit);

    hr = RetrieveSwapSFXState(&m_fEnableSwapSFX);
    IF_FAILED_JUMP(hr, Exit);

    hr = RetrieveSwapMFXState(&m_fEnableSwapMFX);
    IF_FAILED_JUMP(hr, Exit);

    hr = RetrieveDelaySFXState(&m_fEnableDelaySFX);
    IF_FAILED_JUMP(hr, Exit);

    hr = RetrieveDelayMFXState(&m_fEnableDelayMFX);
    IF_FAILED_JUMP(hr, Exit);

    // Update the property page with retrieved information
    SetWindowText(GetDlgItem(hwndDlg, IDC_SPP_ENDPOINT_NAME), pwstrEndpointName);

    // Based on the retrieved states, toggle the checkboxes to reflect them
    if (m_fDisableSysFX)
    {
        CheckDlgButton(hwndDlg, IDC_DISABLE_SYSFX, BST_CHECKED);

        // Disable APO toggling controls on the page
        EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_SWAP_SFX), FALSE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_SWAP_MFX), FALSE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_DELAY_SFX), FALSE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_DELAY_MFX), FALSE);
    }
    else
    {
        CheckDlgButton(hwndDlg, IDC_DISABLE_SYSFX, BST_UNCHECKED);

        // Enable APO toggling controls on the page
        EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_SWAP_SFX), TRUE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_SWAP_MFX), TRUE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_DELAY_SFX), TRUE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE_DELAY_MFX), TRUE);
    }

    if (m_fEnableSwapSFX)
    {
        CheckDlgButton(hwndDlg, IDC_ENABLE_SWAP_SFX, BST_CHECKED);
    }
    else
    {
        CheckDlgButton(hwndDlg, IDC_ENABLE_SWAP_SFX, BST_UNCHECKED);
    }

    if (m_fEnableSwapMFX)
    {
        CheckDlgButton(hwndDlg, IDC_ENABLE_SWAP_MFX, BST_CHECKED);
    }
    else
    {
        CheckDlgButton(hwndDlg, IDC_ENABLE_SWAP_MFX, BST_UNCHECKED);
    }

    if (m_fEnableDelaySFX)
    {
        CheckDlgButton(hwndDlg, IDC_ENABLE_DELAY_SFX, BST_CHECKED);
    }
    else
    {
        CheckDlgButton(hwndDlg, IDC_ENABLE_DELAY_SFX, BST_UNCHECKED);
    }

    if (m_fEnableDelayMFX)
    {
        CheckDlgButton(hwndDlg, IDC_ENABLE_DELAY_MFX, BST_CHECKED);
    }
    else
    {
        CheckDlgButton(hwndDlg, IDC_ENABLE_DELAY_MFX, BST_UNCHECKED);
    }

Exit:
    SAFE_COTASKMEMFREE(pwstrEndpointName);
    return(FALSE);
}
///////////////////////////////////////////////////////////////////////////////
// Function:
//      GetMicArrayGeometry()
//
// Description:
//      Obtains the geometry for the specified mic array.
//
// Parameters:  szDeviceId -- The requested device ID, which can be obtained
//                            from calling EnumAudioCaptureDevices()
//              
//              ppGeometry -- Address of the pointer to the mic-array gemometry.  
//                            Caller is ressponsible for calling CoTaskMemFree()
//                            if the call is successfull.
//
//              cbSize -- size of the geometry structure
//
// Returns:     S_OK on success
///////////////////////////////////////////////////////////////////////////////
HRESULT GetMicArrayGeometry(wchar_t szDeviceId[], KSAUDIO_MIC_ARRAY_GEOMETRY** ppGeometry, ULONG& cbSize)
{
    HRESULT hr = S_OK;

    if (szDeviceId == NULL)
        return E_INVALIDARG;
    if (ppGeometry == NULL)
        return E_POINTER;
   
    cbSize = 0;
    CComPtr<IMMDeviceEnumerator> spEnumerator;
    CComPtr<IMMDevice>           spDevice;
    CComQIPtr<IPart>             spPart;
    bool bIsMicArray;

    hr = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_RETURN(hr);

    hr = spEnumerator->GetDevice(szDeviceId, &spDevice);
    IF_FAILED_RETURN(hr);

    hr = EndpointIsMicArray(spDevice, bIsMicArray);
    IF_FAILED_RETURN(hr);

    if (!bIsMicArray)
        return E_FAIL;
    
    UINT nPartId = 0;
    hr = GetInputJack(spDevice, spPart);
    IF_FAILED_RETURN(hr);

    hr = spPart->GetLocalId(&nPartId);
    IF_FAILED_RETURN(hr);

    CComPtr<IDeviceTopology>     spTopology;
    CComPtr<IMMDeviceEnumerator> spEnum;
    CComPtr<IMMDevice>           spJackDevice;
    CComPtr<IKsControl>          spKsControl;
    wchar_t *                    pwstrDevice = 0;

    // Get the topology object for the part
    hr = spPart->GetTopologyObject(&spTopology);
    IF_FAILED_RETURN(hr);

    // Get the id of the IMMDevice that this topology object describes.
    hr = spTopology->GetDeviceId(&pwstrDevice);
    IF_FAILED_RETURN(hr);

    // Get an IMMDevice pointer using the ID
    hr = spEnum.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hr, Exit);

    hr = spEnum->GetDevice(pwstrDevice, &spJackDevice);
    IF_FAILED_JUMP(hr, Exit);

    // Activate IKsControl on the IMMDevice
    hr = spJackDevice->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, 
                               NULL, reinterpret_cast<void**>(&spKsControl));
    IF_FAILED_JUMP(hr, Exit);

    // At this point we can use IKsControl just as we would use DeviceIoControl
    KSP_PIN ksp;
    ULONG   cbData     = 0;
    ULONG   cbGeometry = 0;

    // Inititialize the pin property
    ::ZeroMemory(&ksp, sizeof(ksp));
    ksp.Property.Set     = KSPROPSETID_Audio;
    ksp.Property.Id      = KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY;
    ksp.Property.Flags   = KSPROPERTY_TYPE_GET;
    ksp.PinId            = nPartId & PARTID_MASK;  

    // Get data size by passing NULL
    hr = spKsControl->KsProperty(reinterpret_cast<PKSPROPERTY>(&ksp), 
                                sizeof(ksp), NULL, 0, &cbGeometry);
    IF_FAILED_JUMP(hr, Exit);
   
    // Allocate memory for the microphone array geometry
    *ppGeometry = reinterpret_cast<KSAUDIO_MIC_ARRAY_GEOMETRY*>
                                   (::CoTaskMemAlloc(cbGeometry));

    if(*ppGeometry == 0)
    {
        hr = E_OUTOFMEMORY;
    }
    IF_FAILED_JUMP(hr, Exit);
   
    // Now retriev the mic-array structure...
    DWORD cbOut = 0;
    hr = spKsControl->KsProperty(reinterpret_cast<PKSPROPERTY>(&ksp), 
                                sizeof(ksp), *ppGeometry, cbGeometry,
                                &cbOut);
    IF_FAILED_JUMP(hr, Exit);
    cbSize = cbGeometry;
   
Exit:
    if(pwstrDevice != 0)
    {
        ::CoTaskMemFree(pwstrDevice);
    }
    return hr;
}//GetMicArrayGeometry()
Beispiel #20
0
_Use_decl_annotations_
NTSTATUS
StartDevice
( 
    PDEVICE_OBJECT          DeviceObject,     
    PIRP                    Irp,              
    PRESOURCELIST           ResourceList      
)  
{
/*++

Routine Description:

    This function is called by the operating system when the device is 
    started.
    It is responsible for starting the miniports.  This code is specific to    
    the adapter because it calls out miniports for functions that are specific 
    to the adapter.                                                            

Arguments:

    DeviceObject - pointer to the driver object

    Irp - pointer to the irp 

    ResourceList - pointer to the resource list assigned by PnP manager

Return Value:

    NT status code

--*/
    PAGED_CODE();

    UNREFERENCED_PARAMETER(ResourceList);

    ASSERT(DeviceObject);
    ASSERT(Irp);
    ASSERT(ResourceList);

    NTSTATUS                    ntStatus        = STATUS_SUCCESS;

    PADAPTERCOMMON              pAdapterCommon  = NULL;
    PUNKNOWN                    pUnknownCommon  = NULL;
    PortClassDeviceContext*     pExtension      = static_cast<PortClassDeviceContext*>(DeviceObject->DeviceExtension);

    DPF_ENTER(("[StartDevice]"));

    //
    // create a new adapter common object
    //
    ntStatus = NewAdapterCommon( 
                                &pUnknownCommon,
                                IID_IAdapterCommon,
                                NULL,
                                NonPagedPoolNx 
                                );
    IF_FAILED_JUMP(ntStatus, Exit);

    ntStatus = pUnknownCommon->QueryInterface( IID_IAdapterCommon,(PVOID *) &pAdapterCommon);
    IF_FAILED_JUMP(ntStatus, Exit);

    ntStatus = pAdapterCommon->Init(DeviceObject);
    IF_FAILED_JUMP(ntStatus, Exit);

    //
    // register with PortCls for power-management services
    ntStatus = PcRegisterAdapterPowerManagement( PUNKNOWN(pAdapterCommon), DeviceObject);
    IF_FAILED_JUMP(ntStatus, Exit);

    //
    // Install wave+topology filters for render devices
    //
    ntStatus = InstallAllRenderFilters(DeviceObject, Irp, pAdapterCommon);
    IF_FAILED_JUMP(ntStatus, Exit);

Exit:

    //
    // Stash the adapter common object in the device extension so
    // we can access it for cleanup on stop/removal.
    //
    if (pAdapterCommon)
    {
        ASSERT(pExtension != NULL);
        pExtension->m_pCommon = pAdapterCommon;
    }

    //
    // Release the adapter IUnknown interface.
    //
    SAFE_RELEASE(pUnknownCommon);
    
    return ntStatus;
}