Skip to content

Instantly share code, notes, and snippets.

@surinkim
Last active October 5, 2015 16:56
Show Gist options
  • Save surinkim/efe4782d0efb501f692d to your computer and use it in GitHub Desktop.
Save surinkim/efe4782d0efb501f692d to your computer and use it in GitHub Desktop.
xp audio handling
/*
이 클래스는 xp이면, Windows Audio Mixer API를,
vista 이후 버전이면, WASAPI를 사용하여 Speaker/Mic를 제어할 수 있게 한다.
참고로, WASAPI(Windows Audio Session API)는 vista 이후 버전만 지원한다.
Windows Audio Mixer API로도, vista 이후 버전에서 speaker 장치의 대부분 기능을 제어할 수 있지만,
결정적으로, Master Volume을 조정할 수 없는 약점이 있다.
Mic 제어는 Windows Audio Mixer API로 xp/win7 모두 제어가능하다.
따라서, Mic 제어는 os 구분없이 Windows Audio Mixer API를 사용한다.
*/
#ifndef AUDIO_WRAPPER_H_
#define AUDIO_WRAPPER_H_
#include <Windows.h>
#include <WinDef.h>
#include <string>
#include <vector> // to remove
#include <QMetaType> // to remove
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <audiopolicy.h>
#pragma comment( lib, "Winmm.lib")
// to remove
struct OutputDeviceInfo
{
OutputDeviceInfo() : m_name(L""), m_mixer( NULL ), m_masterLineId( 0 ), m_waveLineId( 0 ) {};
std::wstring m_name;
HMIXER m_mixer;
DWORD m_masterLineId;
DWORD m_waveLineId;
};
Q_DECLARE_METATYPE( OutputDeviceInfo );
struct InputDeviceInfo
{
InputDeviceInfo() : m_name(L""), m_mixer( NULL ), m_channelCount( 0 ), m_micVolumeControlId( 0 ), m_lineId( 0 ) {};
std::wstring m_name;
HMIXER m_mixer;
DWORD m_channelCount;
DWORD m_micVolumeControlId;
DWORD m_micMuteControlId;
DWORD m_lineId;
};
Q_DECLARE_METATYPE( InputDeviceInfo );
class AudioWrapper
{
public:
AudioWrapper(void);
~AudioWrapper(void);
static bool IsVistaLater();
bool Init();
// 마스터 볼륨 조정( xp, win7 별도)
bool SetMasterVolume( std::wstring deviceName, std::wstring deviceId, const int volume );
int GetMasterVolume( std::wstring deviceName, std::wstring deviceId );
bool SetMasterMute( std::wstring deviceName, std::wstring deviceId, int state );
bool GetMasterMute( std::wstring deviceName, std::wstring deviceId );
// 웨이브 볼륨 조정( xp, win7 별도)
bool SetWaveVolume( std::wstring deviceName, const int volume );
int GetWaveVolume( std::wstring deviceName );
bool SetWaveMute( std::wstring deviceName, int state );
bool GetWaveMute( std::wstring deviceName );
// 마이크 조정( xp, win7 공용 )
bool SetMicVolume( std::wstring deviceName, int value );
int GetMicVolume( std::wstring deviceName );
bool SetMicMute( std::wstring deviceName, int state );
bool GetMicMute( std::wstring deviceName );
// to remove
std::vector< OutputDeviceInfo > GetSpeakerDevices(); // Get Speaker Devices
std::vector< InputDeviceInfo > GetMicDevices(); // Get Mic Devices
void SetCurrentSpeakerDevice( OutputDeviceInfo info ) { m_curOutputDevice = info; }
void SetCurrentMicDevice( InputDeviceInfo info ) { m_curInputDevice = info; }
private:
// xp 전용 control type
enum ControlType
{
MASTER = 0,
WAVE,
};
// 캐싱되는 마이크 Device 정보( xp/win7 공용 )
struct MicDevice
{
HMIXER m_mixer;
MIXERLINE m_mixerLine;
MIXERCONTROL m_mixerVolumeControl; // 마이크 볼륨 컨트롤
MIXERCONTROL m_mixerMuteControl; // 마이크 mute 컨트롤
};
// 캐싱되는 스피커 Device 정보( xp 전용 )
struct SpeakerDevice
{
HMIXER m_mixer;
MIXERLINE m_mixerMasterLine; // 마스터 볼륨 line id
MIXERLINE m_mixerWaveLine; // 웨이브 볼륨 line id
};
// master volume
bool SetMasterVolumeWin7( std::wstring deviceId, const int volume );
bool SetMasterVolumeXp( std::wstring deviceName, const int volume );
int GetMasterVolumeWin7( std::wstring deviceId );
int GetMasterVolumeXp( std::wstring deviceName );
bool SetMasterMuteWin7( std::wstring deviceId, int state );
bool SetMasterMuteXp( std::wstring deviceName, int state );
bool GetMasterMuteWin7( std::wstring deviceId );
bool GetMasterMuteXp( std::wstring deviceName );
// wave volume
bool SetWaveVolumeWin7( const int volume );
bool SetWaveVolumeXp( std::wstring deviceName, int value );
int GetWaveVolumeWin7();
int GetWaveVolumeXp( std::wstring deviceName );
bool SetWaveMuteWin7( int state );
bool SetWaveMuteXp( std::wstring deviceName, int state );
bool GetWaveMuteWin7();
bool GetWaveMuteXp( std::wstring deviceName );
// helper functions
bool FindDevice( std::wstring deviceId, IMMDevice **pDevice ); //device id로 IMMDevice를 찾음.
bool FindControl( IAudioSessionControl2 **pControl2 ); //현재 process id로 IAudioSessionControl2를 찾음.
bool GetMixerCaps( const std::wstring deviceName, HMIXER& findMixer, const int mixerLineType, MIXERCAPS& findMixerCaps );
bool GetMixerLine( const HMIXER& mixer, const MIXERCAPS& mixerCaps, const int mixerLineType, MIXERLINE& findMixerLine );
bool GetMixerWaveLine( const HMIXER& mixer, const MIXERLINE& mixerLine, MIXERLINE& findMixerLine );
bool GetMixerControl( const HMIXER& mixer, const MIXERLINE& mixerLine, const int controlType, MIXERCONTROL& findControl );
bool GetMicDeviceInfo( std::wstring deviceName, MicDevice& micDevice ); //cache MicDevice
bool GetSpeakerDeviceInfo( std::wstring deviceName, SpeakerDevice& speakerDevice ); //cache SpeakerDevice
// xp 전용 function
bool SetVolume( ControlType type, std::wstring deviceName, int value );
int GetVolume( ControlType type, std::wstring deviceName );
bool SetMute( ControlType type, std::wstring deviceName, int state );
bool GetMute( ControlType type, std::wstring deviceName );
std::map< std::wstring, MicDevice> m_mapMicDevice; //한번이라도 검색된 마이크 mixer 정보를 저장하기 위한 map;
std::map< std::wstring, SpeakerDevice> m_mapSpeakerDevice; //한번이라도 검색된 스피커 mixer 정보를 저장하기 위한 map;
bool m_isVistaLater; //비스타 이후 버전이면 true, 이전 버전이면 false
DWORD m_curPid; //현재 프로세스 id
// to remove
OutputDeviceInfo m_curOutputDevice;
InputDeviceInfo m_curInputDevice;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment