/////////////////////////////////////////////////////////////////////////////// // 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()