Uç Nokta Birim Denetimleri
ISimpleAudioVolume, IChannelAudioVolumeve IAudioStreamVolume arabirimleri, istemcilerin paylaşılan mod ses akışlarının koleksiyonları olan ses oturumlarının ses düzeylerini denetlemesini sağlar. Bu arabirimler özel mod ses akışlarıyla çalışmaz.
Özel mod akışlarını yöneten uygulamalar, bu akışların birim düzeylerini IAudioEndpointVolume arabirimi aracılığıyla denetleyebilir. Bu arabirim, ses uç noktası cihazının ses düzeyinidenetler. Ses donanımı böyle bir denetim uygularsa uç nokta cihazı için donanım ses düzeyi denetimini kullanır. Aksi takdirde IAudioEndpointVolume arabirimi, yazılımda birim denetimini uygular.
Bir cihazın donanım ses denetimi varsa, IAudioEndpointVolume arabirimi aracılığıyla denetimde yapılan değişiklikler hem paylaşılan modda hem de özel kullanım modunda ses düzeyini etkiler. Bir cihazda donanım hacmi ve sessiz denetimleri yoksa, yazılım biriminde yapılan değişiklikler ve bu arabirim aracılığıyla denetimlerin sesini kapatma, paylaşılan modda birim düzeyini etkiler, ancak özel kullanım modunda etkilemez. Özel kullanım modunda uygulama ve ses donanımı, yazılım denetimlerini atlayarak ses verilerini doğrudan değiştirir.
Genel bir kural olarak, uygulamalar paylaşılan mod akışlarının birim düzeylerini denetlemek için IAudioEndpointVolume arabirimini kullanmaktan kaçınmalıdır. Bunun yerine, uygulamalar ISimpleAudioVolume, IChannelAudioVolumeveya bu amaçla IAudioStreamVolume arabirimini kullanmalıdır.
Bir uygulama, bir ses uç noktası cihazının ses düzeyini denetlemek için IAudioEndpointVolume arabirimini kullanan bir birim denetimi görüntülerse, bu birim denetimi sistem birim denetimi programı Sndvol tarafından görüntülenen uç nokta birim denetimini yansıtmalıdır. Daha önce açıklandığı gibi, uç nokta birim denetimi Sndvol penceresinin sol tarafında, cihaz etiketli grup kutusundagörünür. Kullanıcı Sndvol'daki birim denetimi aracılığıyla bir cihazın uç nokta hacmini değiştirirse, uygulamadaki ilgili uç nokta birim denetimi Sndvol'deki denetimle birlikte hareket etmelidir. Benzer şekilde, kullanıcı uygulama penceresindeki uç nokta birim denetimi aracılığıyla birim düzeyini değiştirirse, Sndvol'daki ilgili birim denetimi uygulamanın birim denetimiyle birlikte hareket etmelidir.
Bir uygulama penceresindeki uç nokta birim denetiminin Sndvol'daki uç nokta birim denetimini yansıtdığından emin olmak için, uygulamanın bir IAudioEndpointVolumeCallback arabirimi uygulaması ve bildirimleri almak için bu arabirimi kaydetmesi gerekir. Bundan sonra, kullanıcı Sndvol'da uç nokta birim düzeyini her değiştirdiğinde, uygulama IAudioEndpointVolumeCallback::OnNotify yöntemi aracılığıyla bir bildirim çağrısı alır. Bu çağrı sırasında OnNotify yöntemi, uygulama penceresindeki uç nokta birim denetimini Sndvol'de gösterilen denetim ayarıyla eşleşecek şekilde güncelleştirebilir. Benzer şekilde, kullanıcı uygulama penceresindeki birim denetimi aracılığıyla uç nokta birim düzeyini her değiştirdiğinde, Sndvol bir bildirim alır ve yeni birim düzeyini görüntülemek için uç nokta birim denetimini hemen güncelleştirir.
Aşağıdaki kod örneği, IAudioEndpointVolumeCallback arabiriminin olası uygulamasını gösteren bir üst bilgi dosyasıdır:
// Epvolume.h -- Implementation of IAudioEndpointVolumeCallback interface
#include <windows.h>
#include <commctrl.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include "resource.h"
// Dialog handle from dialog box procedure
extern HWND g_hDlg;
// Client's proprietary event-context GUID
extern GUID g_guidMyContext;
// Maximum volume level on trackbar
#define MAX_VOL 100
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; }
//-----------------------------------------------------------
// Client implementation of IAudioEndpointVolumeCallback
// interface. When a method in the IAudioEndpointVolume
// interface changes the volume level or muting state of the
// endpoint device, the change initiates a call to the
// client's IAudioEndpointVolumeCallback::OnNotify method.
//-----------------------------------------------------------
class CAudioEndpointVolumeCallback : public IAudioEndpointVolumeCallback
{
LONG _cRef;
public:
CAudioEndpointVolumeCallback() :
_cRef(1)
{
}
~CAudioEndpointVolumeCallback()
{
}
// IUnknown methods -- AddRef, Release, and QueryInterface
ULONG STDMETHODCALLTYPE AddRef()
{
return InterlockedIncrement(&_cRef);
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG ulRef = InterlockedDecrement(&_cRef);
if (0 == ulRef)
{
delete this;
}
return ulRef;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface)
{
if (IID_IUnknown == riid)
{
AddRef();
*ppvInterface = (IUnknown*)this;
}
else if (__uuidof(IAudioEndpointVolumeCallback) == riid)
{
AddRef();
*ppvInterface = (IAudioEndpointVolumeCallback*)this;
}
else
{
*ppvInterface = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
// Callback method for endpoint-volume-change notifications.
HRESULT STDMETHODCALLTYPE OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify)
{
if (pNotify == NULL)
{
return E_INVALIDARG;
}
if (g_hDlg != NULL && pNotify->guidEventContext != g_guidMyContext)
{
PostMessage(GetDlgItem(g_hDlg, IDC_CHECK_MUTE), BM_SETCHECK,
(pNotify->bMuted) ? BST_CHECKED : BST_UNCHECKED, 0);
PostMessage(GetDlgItem(g_hDlg, IDC_SLIDER_VOLUME),
TBM_SETPOS, TRUE,
LPARAM((UINT32)(MAX_VOL*pNotify->fMasterVolume + 0.5)));
}
return S_OK;
}
};
Yukarıdaki kod örneğindeki CAudioEndpointVolumeCallback sınıfı, IAudioEndpointVolumeCallback arabiriminin bir uygulamasıdır. IAudioEndpointVolumeCallbackIUnknown'den devraldığından, sınıf tanımı AddRef, Releaseve QueryInterfaceIUnknown yöntemlerinin uygulamalarını içerir. Sınıf tanımındaki OnNotify yöntemi, aşağıdaki yöntemlerden biri uç nokta birim düzeyini her değiştirildiğinde çağrılır:
- IAudioEndpointVolume::SetChannelVolumeLevel
- IAudioEndpointVolume::SetChannelVolumeLevelScalar
- IAudioEndpointVolume::SetMasterVolumeLevel
- IAudioEndpointVolume::SetMasterVolumeLevelScalar
- IAudioEndpointVolume::SetMute
- IAudioEndpointVolume::VolumeStepDown
- IAudioEndpointVolume::VolumeStepUp
Önceki kod örneğinde OnNotify yönteminin uygulanması, görüntülenen birim düzeyini güncelleştirmek için uygulama penceresindeki birim denetimine iletiler gönderir.
Bir uygulama, IAudioEndpointVolumeCallback arabirimini bildirim almak üzere kaydetmek için IAudioEndpointVolume::RegisterControlChangeNotifyyönteminiçağırır. Uygulama artık bildirim gerektirmediğinde, kaydı silmek için IAudioEndpointVolume::UnregisterControlChangeNotify yöntemini çağırır.
Aşağıdaki kod örneği, yukarıdaki kod örneğinde CAudioEndpointVolumeCallback sınıfını kaydetmek ve kaydını kaldırmak için RegisterControlChangeNotify çağıran ve UnregisterControlChangeNotifyyöntemlerinibir Windows uygulamasıdır:
// Epvolume.cpp -- WinMain and dialog box functions
#include "stdafx.h"
#include "Epvolume.h"
HWND g_hDlg = NULL;
GUID g_guidMyContext = GUID_NULL;
static IAudioEndpointVolume *g_pEndptVol = NULL;
static BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
#define EXIT_ON_ERROR(hr) \
if (FAILED(hr)) { goto Exit; }
#define ERROR_CANCEL(hr) \
if (FAILED(hr)) { \
MessageBox(hDlg, TEXT("The program will exit."), \
TEXT("Fatal error"), MB_OK); \
EndDialog(hDlg, TRUE); return TRUE; }
//-----------------------------------------------------------
// WinMain -- Registers an IAudioEndpointVolumeCallback
// interface to monitor endpoint volume level, and opens
// a dialog box that displays a volume control that will
// mirror the endpoint volume control in SndVol.
//-----------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HRESULT hr = S_OK;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
CAudioEndpointVolumeCallback EPVolEvents;
if (hPrevInstance)
{
return 0;
}
CoInitialize(NULL);
hr = CoCreateGuid(&g_guidMyContext);
EXIT_ON_ERROR(hr)
// Get enumerator for audio endpoint devices.
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator),
(void**)&pEnumerator);
EXIT_ON_ERROR(hr)
// Get default audio-rendering device.
hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
EXIT_ON_ERROR(hr)
hr = pDevice->Activate(__uuidof(IAudioEndpointVolume),
CLSCTX_ALL, NULL, (void**)&g_pEndptVol);
EXIT_ON_ERROR(hr)
hr = g_pEndptVol->RegisterControlChangeNotify(
(IAudioEndpointVolumeCallback*)&EPVolEvents);
EXIT_ON_ERROR(hr)
InitCommonControls();
DialogBox(hInstance, L"VOLUMECONTROL", NULL, (DLGPROC)DlgProc);
Exit:
if (FAILED(hr))
{
MessageBox(NULL, TEXT("This program requires Windows Vista."),
TEXT("Error termination"), MB_OK);
}
if (g_pEndptVol != NULL)
{
g_pEndptVol->UnregisterControlChangeNotify(
(IAudioEndpointVolumeCallback*)&EPVolEvents);
}
SAFE_RELEASE(pEnumerator)
SAFE_RELEASE(pDevice)
SAFE_RELEASE(g_pEndptVol)
CoUninitialize();
return 0;
}
//-----------------------------------------------------------
// DlgProc -- Dialog box procedure
//-----------------------------------------------------------
BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HRESULT hr;
BOOL bMute;
float fVolume;
int nVolume;
int nChecked;
switch (message)
{
case WM_INITDIALOG:
g_hDlg = hDlg;
SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME, TBM_SETRANGEMIN, FALSE, 0);
SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME, TBM_SETRANGEMAX, FALSE, MAX_VOL);
hr = g_pEndptVol->GetMute(&bMute);
ERROR_CANCEL(hr)
SendDlgItemMessage(hDlg, IDC_CHECK_MUTE, BM_SETCHECK,
bMute ? BST_CHECKED : BST_UNCHECKED, 0);
hr = g_pEndptVol->GetMasterVolumeLevelScalar(&fVolume);
ERROR_CANCEL(hr)
nVolume = (int)(MAX_VOL*fVolume + 0.5);
SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME, TBM_SETPOS, TRUE, nVolume);
return TRUE;
case WM_HSCROLL:
switch (LOWORD(wParam))
{
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
case SB_LINERIGHT:
case SB_LINELEFT:
case SB_PAGERIGHT:
case SB_PAGELEFT:
case SB_RIGHT:
case SB_LEFT:
// The user moved the volume slider in the dialog box.
SendDlgItemMessage(hDlg, IDC_CHECK_MUTE, BM_SETCHECK, BST_UNCHECKED, 0);
hr = g_pEndptVol->SetMute(FALSE, &g_guidMyContext);
ERROR_CANCEL(hr)
nVolume = SendDlgItemMessage(hDlg, IDC_SLIDER_VOLUME, TBM_GETPOS, 0, 0);
fVolume = (float)nVolume/MAX_VOL;
hr = g_pEndptVol->SetMasterVolumeLevelScalar(fVolume, &g_guidMyContext);
ERROR_CANCEL(hr)
return TRUE;
}
break;
case WM_COMMAND:
switch ((int)LOWORD(wParam))
{
case IDC_CHECK_MUTE:
// The user selected the Mute check box in the dialog box.
nChecked = SendDlgItemMessage(hDlg, IDC_CHECK_MUTE, BM_GETCHECK, 0, 0);
bMute = (BST_CHECKED == nChecked);
hr = g_pEndptVol->SetMute(bMute, &g_guidMyContext);
ERROR_CANCEL(hr)
return TRUE;
case IDCANCEL:
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
}
return FALSE;
}
Yukarıdaki kod örneğinde, WinMain işlevi, IMMDeviceEnumerator arabiriminin bir örneğini oluşturmak için CoCreateInstance işlevini çağırır ve varsayılan işleme cihazının IMMDevice arabirimini almak için IMMDeviceEnumerator::GetDefaultAudioEndpoint yöntemini çağırır. WinMain, cihazın IAudioEndpointVolume arabirimini almak için IMMDevice::Activate yöntemini çağırır ve uygulamayı uç nokta birimi değişikliklerinin bildirimlerini almak üzere kaydetmek için RegisterControlChangeNotifyçağırır. Ardından winmain , cihaz için uç nokta birim denetimini görüntülemek için bir iletişim kutusu açar. İletişim kutusunda ayrıca cihazın sesinin kapalı olup olmadığını gösteren bir onay kutusu da görüntülenir. İletişim kutusundaki uç nokta birim denetimi ve sesini kapat onay kutusu, Sndvol tarafından görüntülenen uç nokta birim denetimi ve sesini kapat onay kutusunun ayarlarını yansıtır. WinMain ve CoCreateInstancehakkında daha fazla bilgi için Windows SDK belgelerine bakın. IMMDeviceEnumerator ve IMMDevicehakkında daha fazla bilgi için bkz. ses cihazlarını numaralandırma .
Önceki kod örneğinde yer alan DlgProc iletişim kutusu yordamı, kullanıcının birimde yaptığı değişiklikleri işler ve iletişim kutusundaki denetimler aracılığıyla ayarları kapatır. DlgProc, SetMasterVolumeLevelScalarveya SetMuteçağırdığında, Sndvol değişiklik bildirimini alır ve penceresindeki ilgili denetimi yeni birim veya sessiz ayarını yansıtacak şekilde güncelleştirir. kullanıcı, iletişim kutusunu kullanmak yerine Sndvol penceresindeki denetimler aracılığıyla birimi güncelleştirir ve ayarları kapatırsa , CAudioEndpointVolumeCallback sınıfındaki OnNotify yöntemi yeni ayarları görüntülemek için iletişim kutusundaki denetimleri güncelleştirir.
Kullanıcı iletişim kutusundaki denetimler aracılığıyla birimi değiştirirse, CAudioEndpointVolumeCallback sınıfındaki OnNotify yöntemi iletişim kutusundaki denetimleri güncelleştirmek için ileti göndermez. Bunu yapmak yedekli olur. OnNotify, iletişim kutusundaki denetimleri yalnızca birim değişikliği Sndvol'dan veya başka bir uygulamadan kaynaklanıyorsa güncelleştirir. DlgProc işlevindeki SetMasterVolumeLevelScalar ve SetMute yöntemi çağrılarındaki ikinci parametre, yöntemlerden herhangi biri onNotify ileten olay bağlamı GUID'sine yönelik bir işaretçidir. OnNotify, iletişim kutusunun birim değişikliğinin kaynağı olup olmadığını belirlemek için olay bağlamı GUID değerini denetler. Olay bağlamı GUID'leri hakkında daha fazla bilgi için bkz. IAudioEndpointVolumeCallback::OnNotify.
Kullanıcı iletişim kutusundan çıktığında, önceki kod örneğindeki UnregisterControlChangeNotifyçağrısı, program sonlandırılmadan önce CAudioEndpointVolumeCallback sınıfının kaydını siler.
Varsayılan yakalama cihazı için birim ve sesi kapatma denetimlerini görüntülemek için önceki kod örneğini kolayca değiştirebilirsiniz. WinMain işlevinde, çağrıdaki ilk parametrenin değerini eRender'den eCapture'a IMMDeviceEnumerator::GetDefaultAudioEndpoint yöntemine değiştirin.
Aşağıdaki kod örneği, önceki kod örneğinde görünen birimi ve sessize alma denetimlerini tanımlayan kaynak betiğidir:
// Epvolume.rc -- Resource script
#include "resource.h"
#include "windows.h"
#include "commctrl.h"
//
// Dialog box
//
VOLUMECONTROL DIALOGEX 0, 0, 160, 60
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_SETFONT
CAPTION "Audio Endpoint Volume"
FONT 8, "Arial Rounded MT Bold", 400, 0, 0x0
BEGIN
LTEXT "Min",IDC_STATIC_MINVOL,10,10,20,12
RTEXT "Max",IDC_STATIC_MAXVOL,130,10,20,12
CONTROL "",IDC_SLIDER_VOLUME,"msctls_trackbar32",
TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,10,20,140,12
CONTROL "Mute",IDC_CHECK_MUTE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,20,40,70,12
END
Aşağıdaki kod örneği, önceki kod örneklerinde görünen denetim tanımlayıcılarını tanımlayan kaynak üst bilgisi dosyasıdır:
// Resource.h -- Control identifiers (epvolume)
#define IDC_SLIDER_VOLUME 1001
#define IDC_CHECK_MUTE 1002
#define IDC_STATIC_MINVOL 1003
#define IDC_STATIC_MAXVOL 1004
Yukarıdaki kod örnekleri, varsayılan işleme cihazının uç nokta hacmini denetlemek ve izlemek için basit bir uygulama oluşturmak üzere birleştirilir. Daha kullanışlı bir uygulama ayrıca cihazın durumu değiştiğinde kullanıcıya bildirimde bulunabilir. Örneğin, cihaz devre dışı bırakılmış, fişi kaldırılmış veya kaldırılmış olabilir. Bu tür olayları izleme hakkında daha fazla bilgi için bkz. Cihaz Olayları.
İlgili konular