实现代码
播放软件,慢慢地有了声音控制的需求,在网上找了一下,用Core Audio APIS 音频应用开发即可。入门稍慢,不过用起来很简单。整理了一个类供调用。
class TCbwAudioEndpointVolumeCallback;
typedef void __fastcall (__closure * TOnVoiceNotifyEvent)(bool bMuted, int fMasterVolume);
class TCbwVolumeControl {
private:
TCbwAudioEndpointVolumeCallback * EPVolEvents;
TOnVoiceNotifyEvent FOnVoiceNotify;
bool FValid;
bool __fastcall HRStatus(HRESULT hr, UnicodeString info);
void __fastcall Prework();
void __fastcall AfterWork();
int __fastcall GetMasterVolume();
void __fastcall SetMasterVolume(int value);
bool __fastcall GetMuted();
void __fastcall SetMuted(bool value);
public:
__fastcall TCbwVolumeControl();
__fastcall ~TCbwVolumeControl();
__property bool IsValid = { read = FValid };
__property int MasterVolume = { read = GetMasterVolume, write = SetMasterVolume };
__property bool Muted = { read = GetMuted, write = SetMuted };
__property TOnVoiceNotifyEvent OnVoiceNotify = { read = FOnVoiceNotify, write = FOnVoiceNotify };
void __fastcall OnNotifyFromCallback(bool bMuted, float fMasterVolume);
};
extern TCbwVolumeControl * GlobalVolumeControl;
TCbwVolumeControl * GlobalVolumeControl = NULL;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
IAudioEndpointVolume *g_pEndptVol = NULL;
#define SAFE_RELEASE(punk)
if ((punk) != NULL)
{ (punk)->Release(); (punk) = NULL; }
#define EXIT_ON_ERROR(hr)
if (FAILED(hr)) return;
__fastcall TCbwVolumeControl::TCbwVolumeControl() {
EPVolEvents = new TCbwAudioEndpointVolumeCallback;
FOnVoiceNotify = NULL;
EPVolEvents->ParentControl = this;
Prework();
}
__fastcall TCbwVolumeControl::~TCbwVolumeControl() {
AfterWork();
delete EPVolEvents;
}
bool __fastcall TCbwVolumeControl::HRStatus(HRESULT hr, UnicodeString info) {
if (FAILED(hr)) {
DRGRAPH_DEBUG(THelper::FormatString(L"CALL %s FAILED!", info));
return false;
}
return true;
}
void __fastcall TCbwVolumeControl::Prework() {
FValid = false;
pEnumerator = NULL;
pDevice = NULL;
g_pEndptVol = NULL;
GUID g_guidMyContext = GUID_NULL;
CoInitialize(NULL);
if (HRStatus(CoCreateGuid(&g_guidMyContext),
L"CoCreateGuid(&g_guidMyContext)"))
if (HRStatus(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator),
(void**)&pEnumerator), L"CoCreateInstance"))
if (HRStatus(pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole,
&pDevice), L"pEnumerator->GetDefaultAudioEndpoint"))
if (HRStatus(pDevice->Activate(__uuidof(IAudioEndpointVolume),
CLSCTX_ALL, NULL, (void**)&g_pEndptVol),
L"pDevice->Activate"))
if (HRStatus(g_pEndptVol->RegisterControlChangeNotify
((IAudioEndpointVolumeCallback*)EPVolEvents),
L"g_pEndptVol->RegisterControlChangeNotify"))
FValid = true;
}
void __fastcall TCbwVolumeControl::AfterWork() {
if (pEnumerator != NULL) {
HRStatus(g_pEndptVol->UnregisterControlChangeNotify
((IAudioEndpointVolumeCallback*) EPVolEvents),
L"g_pEndptVol->UnregisterControlChangeNotify");
}
SAFE_RELEASE(pEnumerator);
SAFE_RELEASE(pDevice);
SAFE_RELEASE(g_pEndptVol);
CoUninitialize();
}
int __fastcall TCbwVolumeControl::GetMasterVolume() {
float pfLevel = 0;
HRStatus(g_pEndptVol->GetMasterVolumeLevelScalar(&pfLevel),
L"g_pEndptVol->GetMasterVolumeLevel");
return pfLevel * 100 + 0.5;
}
void __fastcall TCbwVolumeControl::SetMasterVolume(int value) {
float fVolume = value / 100.0;
HRStatus(g_pEndptVol->SetMasterVolumeLevelScalar(fVolume,
&GUID_NULL), L"pAudioEndpointVolume->SetMasterVolumeLevelScalar");
}
void __fastcall TCbwVolumeControl::OnNotifyFromCallback(bool bMuted,
float fMasterVolume) {
if (FOnVoiceNotify)
FOnVoiceNotify(bMuted, fMasterVolume * 100 + 0.5);
}
bool __fastcall TCbwVolumeControl::GetMuted() {
int muted = false;
g_pEndptVol->GetMute(&muted);
return muted;
}
void __fastcall TCbwVolumeControl::SetMuted(bool value) {
HRStatus(g_pEndptVol->SetMute(value,
&GUID_NULL), L"pAudioEndpointVolume->SetMute");
}
演示效果
简单做了一个测试界面。
void __fastcall TMainForm::OnVoiceNotify(bool bMuted, int fMasterVolume) {
Button_Mute->EditValue = bMuted;
Button_Volume->EditValue = fMasterVolume;
}
void __fastcall TMainForm::Button_MutePropertiesEditValueChanged(TObject *Sender) {
bool muted = Button_Mute->CurEditValue;
int volume = Button_Volume->CurEditValue;
ShowStatus(THelper::FormatString(L"%d, %s", volume, muted ? L"Muted" : L"Sound"));
FVolumeControl->MasterVolume = volume;
FVolumeControl->Muted = muted;
}