⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 volumeapi.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//

#include "VolumeApi.hpp"
#include "Common.hpp"
#include "Debug.hpp"
#include <regext.h>
#include "VoIPNotify.hpp"
#include "VolumeAPI.hpp"

const DWORD c_MaxVolume = 0xFFFF; 

class Mixer_t
{
public:
    Mixer_t();
    ~Mixer_t();
    
    HRESULT 
    Open(
        void
        );
    
    HRESULT 
    SetSourceVolume(
        DWORD Volume
        );
    
    HRESULT 
    GetSourceVolume(
        __out DWORD* pVolume
        );

private: 
    
    HRESULT 
    GetCaptureSource(
        UINT* pSourceIndex
        );

private:

    static  const WCHAR sc_DeviceIdPath[]; 
    static  const WCHAR sc_DeviceIdValue[]; 
    
    HMIXEROBJ       m_MixerHandle;                          // mixer handle
    UINT            m_MuxID;                                // control ID for the source Mux

    UINT            m_SourcesCount;                         // number of capture sources (e.g. CD, Aux, Mic)
    DWORD           m_VolumeControlIdOfCaptureSource;       // Volume control Id of current capture source
};


const WCHAR Mixer_t::sc_DeviceIdPath[]  = L"System\\State\\VoIP"; 
const WCHAR Mixer_t::sc_DeviceIdValue[] = L"Mixer Device Id"; 

Mixer_t::Mixer_t()
    : m_MixerHandle(NULL)
{
    ; 
}

Mixer_t::~Mixer_t()
{
    if (m_MixerHandle != NULL) 
    {
        mixerClose((HMIXER) m_MixerHandle);
    }
}

/*------------------------------------------------------------------------------
    Mixer_t::Open
    
    Description
    
    Parameters:
        DeviceId: 
------------------------------------------------------------------------------*/
HRESULT
Mixer_t::Open(
    void
    )
{   
    DWORD DeviceId = 0; 

    // trying to get the device Id from registry, if it failed, we use the default device id, which is 0
    RegistryGetDWORD(
        HKEY_LOCAL_MACHINE, 
        sc_DeviceIdPath, 
        sc_DeviceIdValue, 
        &DeviceId
        ); 
    
    // Start off by opening the device, using the device ID
    MMRESULT MMResult = mixerOpen((HMIXER *) &m_MixerHandle, static_cast<UINT>(DeviceId), 0, 0, 0);
    if (MMResult != MMSYSERR_NOERROR)
    {
        COMMON_DEBUGMSG(ZONE_COMMON_ERROR, (L"Failed at opening mixer for device %d", DeviceId)); 
        return CommonUtilities_t::ToHR(MMResult); 
    }

    ASSERT(m_MixerHandle != NULL); 

    // Mixer devices expose several different lines, one for each input/output source
    // Find the line corresponding to PCM capture
    MIXERLINE MixerLine;
    MixerLine.cbStruct = sizeof(MixerLine);
    MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
    
    MMResult = mixerGetLineInfo(m_MixerHandle, &MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
    if (MMResult != MMSYSERR_NOERROR)
    {
        return CommonUtilities_t::ToHR(MMResult); 
    }

    m_SourcesCount = MixerLine.cConnections;

    // wave-in destinations have a Multiplexer (mux) control to select between input sources
    // we need the Control ID for the capture source select mux 
    MIXERCONTROL MixerControl;
    MixerControl.cbStruct = sizeof(MixerControl);

    MIXERLINECONTROLS MixerControlQuery;
    MixerControlQuery.cbStruct      = sizeof(MixerControlQuery);
    MixerControlQuery.dwLineID      = MixerLine.dwLineID;
    MixerControlQuery.cControls     = 1;
    MixerControlQuery.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
    MixerControlQuery.cbmxctrl      = sizeof(MixerControl);
    MixerControlQuery.pamxctrl      = &MixerControl;
    
    MMResult = mixerGetLineControls(m_MixerHandle, &MixerControlQuery, MIXER_GETLINECONTROLSF_ONEBYTYPE);
    if (MMResult != MMSYSERR_NOERROR)
    {
        return CommonUtilities_t::ToHR(MMResult); 
    }
    

    if (MixerControl.dwControlType != MIXERCONTROL_CONTROLTYPE_MUX ||
        MixerControl.cMultipleItems != m_SourcesCount) 
    {
        // something's gone terribly wrong
        COMMON_DEBUGMSG(ZONE_COMMON_ERROR, (L"The control is not a mux, or doesn't have the right number of entries!\n"));
        return E_UNEXPECTED;
    }

    m_MuxID = MixerControl.dwControlID;

    UINT CurrentCaptureSourceId; 
    HRESULT hr = GetCaptureSource(&CurrentCaptureSourceId); 
    if (FAILED(hr))
    {
        return hr; 
    }
    
    MIXERLINE SourceLine; 
    
    // first, retrieve the info for the source line
    SourceLine.cbStruct         = sizeof(SourceLine);
    SourceLine.dwDestination    = MixerLine.dwDestination;
    SourceLine.dwSource         = CurrentCaptureSourceId;
    MMResult = mixerGetLineInfo(m_MixerHandle,&SourceLine, MIXER_GETLINEINFOF_SOURCE);
    if (MMResult != MMSYSERR_NOERROR)
    {
        return CommonUtilities_t::ToHR(MMResult); 
    }

    // now, retrieve the info for the volume control for the source line
    memset(&MixerControl, 0, sizeof(MIXERCONTROL));     
    MixerControl.cbStruct = sizeof(MixerControl);    

    memset(&MixerControlQuery, 0, sizeof(MIXERLINECONTROLS));
    MixerControlQuery.cbStruct      = sizeof(MixerControlQuery);
    MixerControlQuery.dwLineID      = SourceLine.dwLineID;
    MixerControlQuery.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
    MixerControlQuery.cControls     = 1;
    MixerControlQuery.cbmxctrl      = sizeof(MixerControl);
    MixerControlQuery.pamxctrl      = &MixerControl;
    

    MMResult = mixerGetLineControls(m_MixerHandle, &MixerControlQuery, MIXER_GETLINECONTROLSF_ONEBYTYPE);
    if (MMResult != MMSYSERR_NOERROR)
    {
        return CommonUtilities_t::ToHR(MMResult); 
    }


    m_VolumeControlIdOfCaptureSource = MixerControl.dwControlID; 

    return S_OK;
}

/*------------------------------------------------------------------------------
    Mixer_t::SetSourceVolume
    
    Uses mixerSetControlDetails to set the volume for a particular capture source
------------------------------------------------------------------------------*/
HRESULT
Mixer_t::SetSourceVolume(
    DWORD Volume
    )
{
    if (m_MixerHandle == NULL)
    {
        return E_UNEXPECTED; 
    }

    Volume = LOWORD(Volume); // the volume should ranges from 0x0000 - 0xffff
    
    MMRESULT MMResult;
    MIXERCONTROLDETAILS MixerDetails;

    MixerDetails.cbStruct       = sizeof(MixerDetails);
    MixerDetails.dwControlID    = m_VolumeControlIdOfCaptureSource;
    MixerDetails.cChannels      = 1;
    MixerDetails.cMultipleItems = 0;
    MixerDetails.cbDetails      = sizeof(DWORD);
    MixerDetails.paDetails      = &Volume;

    MMResult = mixerSetControlDetails(m_MixerHandle, &MixerDetails, MIXER_SETCONTROLDETAILSF_VALUE );
    if (MMResult != MMSYSERR_NOERROR)
    {
        COMMON_DEBUGMSG(ZONE_COMMON_ERROR, (L"Failed at setting source volume!")); 
        return CommonUtilities_t::ToHR(MMResult); 
    }

    return S_OK;
}

/*------------------------------------------------------------------------------
    Mixer_t::GetSourceVolume
    
    Uses mixerGetControlDetails to get the volume for a particular capture source
------------------------------------------------------------------------------*/
HRESULT
Mixer_t::GetSourceVolume(
    DWORD* pVolume
    )
{
    if (pVolume == NULL)
    {
        return E_INVALIDARG; 
    }

    *pVolume = 0; 

    if (m_MixerHandle == NULL)
    {
        return E_UNEXPECTED; 
    }
    
    MMRESULT MMResult;
    MIXERCONTROLDETAILS MixerDetails;

    MixerDetails.cbStruct       = sizeof(MixerDetails);
    MixerDetails.dwControlID    = m_VolumeControlIdOfCaptureSource;
    MixerDetails.cChannels      = 1;
    MixerDetails.cMultipleItems = 0;
    MixerDetails.cbDetails      = sizeof(DWORD);
    MixerDetails.paDetails      = pVolume;

    MMResult = mixerGetControlDetails(m_MixerHandle, &MixerDetails, MIXER_GETCONTROLDETAILSF_VALUE );
    if (MMResult != MMSYSERR_NOERROR)
    {
        COMMON_DEBUGMSG(ZONE_COMMON_ERROR, (L"Failed at setting source volume!")); 
        return CommonUtilities_t::ToHR(MMResult); 
    }

    return S_OK;
}

/*------------------------------------------------------------------------------
    Mixer_t::GetCaptureSource
    
    uses mixerGetControlDetails to query the state of the record-select mux

    Note that mux controls return their state in a peculiar way. Rather 
    than return the index of the selected source, the mux control wants
    to fill in an array of booleans with a unique entry set to TRUE, corresponding
    to the selected source.
------------------------------------------------------------------------------*/
HRESULT
Mixer_t::GetCaptureSource(
    UINT* pSourceIndex
    )
{
    if (pSourceIndex == NULL)
    {
        return E_INVALIDARG; 
    }

    *pSourceIndex = 0; 

    if (m_MixerHandle == NULL)
    {
        return E_UNEXPECTED; 
    }
    
    // allocate and populate the source table and mux-setting table
    BOOL* pMuxTable = new BOOL[m_SourcesCount];
    if (pMuxTable == NULL) 
    {
        return E_OUTOFMEMORY;
    }
    // clear the mux table to be sure we get the real scoop from the driver
    memset(pMuxTable, 0, m_SourcesCount * sizeof(pMuxTable[0]));

    MMRESULT MMResult;
    HRESULT  hr = E_FAIL; 
    
    MIXERCONTROLDETAILS MuxSetting;
    MuxSetting.cbStruct = sizeof(MuxSetting);
    MuxSetting.hwndOwner = NULL;
    MuxSetting.cChannels = 1;
    MuxSetting.cMultipleItems = m_SourcesCount;
    MuxSetting.dwControlID = m_MuxID;
    MuxSetting.paDetails = pMuxTable;
    MuxSetting.cbDetails = m_SourcesCount * sizeof(pMuxTable[0]);

    MMResult = mixerGetControlDetails(m_MixerHandle, &MuxSetting, MIXER_GETCONTROLDETAILSF_VALUE );
    if (MMResult != MMSYSERR_NOERROR)
    {
        hr = CommonUtilities_t::ToHR(MMResult); 
        goto exit; 
    }

    for (UINT i=0; i < m_SourcesCount; i++) 
    {
        if (pMuxTable[i]) 
        {
            *pSourceIndex = i;
            hr = S_OK; 
            break; 
        }
    }

exit:     

    if (pMuxTable != NULL)
    {
        delete [] pMuxTable;        
    }

    return hr; 
   
}

/*------------------------------------------------------------------------------
    UIVolumeToAudioVolume
    
    Convert UI volume to audio volume
------------------------------------------------------------------------------*/
DWORD
UIVolumeToAudioVolume(
    DWORD   UIVolume, 
    bool    Stereo
    )
{
    if (UIVolume < 0 || UIVolume > c_MaxUIVolume)
    {
        return 0; 
    }

    DWORD AudioVolume = (UIVolume * c_MaxVolume / c_MaxUIVolume); 

    if (Stereo)
    {
        AudioVolume = LOWORD(AudioVolume) | (LOWORD(AudioVolume) << 16);     
    }

    return AudioVolume;     
}

/*------------------------------------------------------------------------------
    AudioVolumeToUIVolume
    
    Convert Audio volume to UI volume
------------------------------------------------------------------------------*/
DWORD
AudioVolumeToUIVolume(
    DWORD AudioVolume
    )
{
    //because UI volume and audio volume have different scale, it is possible that 2 adjacent volume 
    //can fall into same UI volume slot. Therefore, we need to round up a little bit (c_MaxVolume / c_MaxUIVolume / 2)
    //to make sure they always fall into different UI slot
    return (LOWORD(AudioVolume) + c_MaxVolume / c_MaxUIVolume / 2) * c_MaxUIVolume / c_MaxVolume;         
    
}

/*------------------------------------------------------------------------------
    GetWaveOutVolume
    
    Get true volume from waveOut API
------------------------------------------------------------------------------*/
HRESULT
GetWaveOutVolume(
    __out DWORD*  pVolume
    )
{
    ASSERT(pVolume != NULL); 
    *pVolume = 0; 

    MMRESULT Result = waveOutGetVolume(0, pVolume); 
    if (Result != MMSYSERR_NOERROR) 
    {
        return E_FAIL; 
    }

    *pVolume = AudioVolumeToUIVolume(*pVolume); 

    return S_OK; 
}

/*------------------------------------------------------------------------------
    SetWaveOutVolume
    
    apply the current UI volume to waveOut API   
------------------------------------------------------------------------------*/
HRESULT
SetWaveOutVolume(
    DWORD UIVolume
    )
{
    if (UIVolume < 0 || UIVolume > c_MaxUIVolume)
    {
        return E_INVALIDARG; 
    }

    DWORD Volume = UIVolumeToAudioVolume(UIVolume, true); 

    MMRESULT Result = waveOutSetVolume(0, Volume); 
    if (Result != MMSYSERR_NOERROR)
    {
        return E_FAIL; 
    }

    return S_OK; 

}

/*------------------------------------------------------------------------------
    GetRingerVolume
    
    Get ringer volume    
------------------------------------------------------------------------------*/
HRESULT
GetRingerVolume(
    __out DWORD* pVolume
    )
{
    if (pVolume == NULL)
    {
        return E_INVALIDARG; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -