Visual studio 2017 控制台应用程序与Win32应用程序-DirectSound捕获设备枚举给出不同的结果
我正在寻找一种可靠的方法,将DirectShow捕获设备GUID映射到其相应的waveID值 我在Chris_p中发现了以下内容: 该解决方案非常有效,它依赖于一个相当模糊的Visual studio 2017 控制台应用程序与Win32应用程序-DirectSound捕获设备枚举给出不同的结果,visual-studio-2017,directshow,directsound,Visual Studio 2017,Directshow,Directsound,我正在寻找一种可靠的方法,将DirectShow捕获设备GUID映射到其相应的waveID值 我在Chris_p中发现了以下内容: 该解决方案非常有效,它依赖于一个相当模糊的IKsPropertySet接口来检索映射 不幸的是,如果我尝试从C++/CLI库中使用相同的技术,代码将失败,并出现E_NOTIMPL(此行为已在问题中描述过,-请参阅Vladimir Hmelyoff的回答) 因此,我想我可以编写一个简单的基于控制台的辅助应用程序来检索映射并打印它们。然后,我的库可以启动这个辅助应用程序
IKsPropertySet
接口来检索映射
不幸的是,如果我尝试从C++/CLI库中使用相同的技术,代码将失败,并出现E_NOTIMPL
(此行为已在问题中描述过,-请参阅Vladimir Hmelyoff的回答)
因此,我想我可以编写一个简单的基于控制台的辅助应用程序来检索映射并打印它们。然后,我的库可以启动这个辅助应用程序并解析重定向的输出以获得映射
控制台程序运行正常,但是,传递给枚举回调的GUID与Chris\p的解决方案传递的GUID完全不同。
事实上,它们都具有相同的基本结构:
lpGuid = 0x02ad0808 {BDF35A00-B9AC-11D0-A619-00AA00A7C000}
唯一的变化发生在GUID的最后几位,它们恰好与映射的waveId值匹配。
另一件奇怪的事情是,捕获设备描述被截断为31个字符,就好像枚举是使用WaveIn API执行的一样
似乎有些DirectSound facade现在正在包装WaveIn API
是否有任何关于可能发生的情况的指针?我是否可以禁用此行为并枚举WIN32应用程序正在枚举的相同GUID?
以下是控制台应用程序的代码:
#include "stdafx.h"
#include <mmreg.h>
#include <initguid.h>
#include <Dsound.h>
#include <dsconf.h>
static BOOL CALLBACK DSEnumCallback(
LPGUID lpGuid,
LPCTSTR lpcstrDescription,
LPCTSTR lpcstrModule,
LPVOID lpContext
);
static BOOL GetInfoFromDSoundGUID(GUID i_sGUID, DWORD &dwWaveID);
static HRESULT DirectSoundPrivateCreate(OUT LPKSPROPERTYSET * ppKsPropertySet);
typedef WINUSERAPI HRESULT(WINAPI *LPFNDLLGETCLASSOBJECT) (const CLSID &, const IID &, void **);
BOOL GetInfoFromDSoundGUID(GUID i_sGUID, DWORD &dwWaveID) {
LPKSPROPERTYSET pKsPropertySet = NULL;
HRESULT hr;
BOOL retval = FALSE;
PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA psDirectSoundDeviceDescription = NULL;
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA sDirectSoundDeviceDescription;
memset(&sDirectSoundDeviceDescription, 0, sizeof(sDirectSoundDeviceDescription));
hr = DirectSoundPrivateCreate(&pKsPropertySet);
if( SUCCEEDED(hr) ) {
ULONG ulBytesReturned = 0;
sDirectSoundDeviceDescription.DeviceId = i_sGUID;
// On the first call the final size is unknown so pass the size of the struct in order to receive
// "Type" and "DataFlow" values, ulBytesReturned will be populated with bytes required for struct+strings.
hr = pKsPropertySet->Get(DSPROPSETID_DirectSoundDevice,
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
NULL,
0,
&sDirectSoundDeviceDescription,
sizeof(sDirectSoundDeviceDescription),
&ulBytesReturned
);
if( ulBytesReturned ) {
// On the first call it notifies us of the required amount of memory in order to receive the strings.
// Allocate the required memory, the strings will be pointed to the memory space directly after the struct.
psDirectSoundDeviceDescription = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA)new BYTE[ulBytesReturned];
*psDirectSoundDeviceDescription = sDirectSoundDeviceDescription;
hr = pKsPropertySet->Get(DSPROPSETID_DirectSoundDevice,
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
NULL,
0,
psDirectSoundDeviceDescription,
ulBytesReturned,
&ulBytesReturned
);
dwWaveID = psDirectSoundDeviceDescription->WaveDeviceId;
delete[] psDirectSoundDeviceDescription;
retval = TRUE;
}
pKsPropertySet->Release();
}
return retval;
}
HRESULT DirectSoundPrivateCreate(OUT LPKSPROPERTYSET * ppKsPropertySet) {
HMODULE hLibDsound = NULL;
LPFNDLLGETCLASSOBJECT pfnDllGetClassObject = NULL;
LPCLASSFACTORY pClassFactory = NULL;
LPKSPROPERTYSET pKsPropertySet = NULL;
HRESULT hr = DS_OK;
// Load dsound.dll
hLibDsound = LoadLibrary(TEXT("dsound.dll"));
if( !hLibDsound ) {
hr = DSERR_GENERIC;
}
// Find DllGetClassObject
if( SUCCEEDED(hr) ) {
pfnDllGetClassObject =
(LPFNDLLGETCLASSOBJECT)GetProcAddress(hLibDsound, "DllGetClassObject");
if( !pfnDllGetClassObject ) {
hr = DSERR_GENERIC;
}
}
// Create a class factory object
if( SUCCEEDED(hr) ) {
hr = pfnDllGetClassObject(CLSID_DirectSoundPrivate, IID_IClassFactory, (LPVOID *)&pClassFactory);
}
// Create the DirectSoundPrivate object and query for an IKsPropertySet
// interface
if( SUCCEEDED(hr) ) {
hr = pClassFactory->CreateInstance(NULL, IID_IKsPropertySet, (LPVOID *)&pKsPropertySet);
}
// Release the class factory
if( pClassFactory ) {
pClassFactory->Release();
}
// Handle final success or failure
if( SUCCEEDED(hr) ) {
*ppKsPropertySet = pKsPropertySet;
} else if( pKsPropertySet ) {
pKsPropertySet->Release();
}
FreeLibrary(hLibDsound);
return hr;
}
BOOL CALLBACK DSEnumCallback(
LPGUID lpGuid,
LPCTSTR lpcstrDescription,
LPCTSTR lpcstrModule,
LPVOID lpContext
) {
LPWSTR psz = NULL;
StringFromCLSID(*lpGuid, &psz);
DWORD WaveID = 0xFFFFFFFF;
if( lpGuid ) {
GUID i_guid = *lpGuid;
GetInfoFromDSoundGUID(i_guid, WaveID);
}
if( WaveID != 0xFFFFFFFF )
wprintf(_T("%d %s\r\n"), WaveID, psz);
if( psz ) {
CoTaskMemFree(psz);
}
return TRUE;
}
int main()
{
DirectSoundCaptureEnumerate(DSEnumCallback, NULL);
Sleep(10000);
return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
静态BOOL回调DSEnumCallback(
LPGUID LPGUID,
LPCTSTR lpcstrDescription,
LPCTSTR LPCSTRMODEL,
LPVOID lpContext
);
静态BOOL GetInfoFromDSoundGUID(GUID i_sGUID、DWORD和dwWaveID);
静态HRESULT DirectSoundPrivateCreate(输出LPKSPROPERTYSET*ppKsPropertySet);
typedef WINUSERAPI HRESULT(WINAPI*LPFNDLLGETCLASSOBJECT)(常量CLSID&,常量IID&,void**);
BOOL GetInfoFromDSoundGUID(GUID i_sGUID、DWORD和dwWaveID){
LPKSPROPERTYSET pKsPropertySet=NULL;
HRESULT-hr;
BOOL-retval=FALSE;
PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA psDirectSoundDeviceDescription=NULL;
DSPROPERTY\u DIRECTSOUNDDEVICE\u DESCRIPTION\u DATA sDirectSoundDeviceDescription;
memset(&sDirectSoundDeviceDescription,0,sizeof(sDirectSoundDeviceDescription));
hr=DirectSoundPrivateCreate(&pKsPropertySet);
如果(成功(hr)){
ULONG Ulbytes返回值=0;
sDirectSoundDeviceDescription.DeviceId=i\u sGUID;
//第一次调用时,最终大小未知,因此传递结构的大小以接收
//“Type”和“DataFlow”值,ulBytesReturned将填充struct+字符串所需的字节。
hr=pKsPropertySet->Get(DSPROPSETID\u DirectSoundDevice,
DSPROPERTY\u DIRECTSOUNDDEVICE\u说明,
无效的
0,
&D直接声音设备说明,
sizeof(sDirectSoundDeviceDescription),
&乌尔比特斯回来了
);
如果(返回Ulbytes){
//在第一次调用时,它会通知我们接收字符串所需的内存量。
//分配所需的内存,字符串将直接指向结构后的内存空间。
psDirectSoundDeviceDescription=(PDSPProperty_DIRECTSOUNDDEVICE_DESCRIPTION_DATA)新字节[ulBytesReturned];
*psDirectSoundDeviceDescription=sDirectSoundDeviceDescription;
hr=pKsPropertySet->Get(DSPROPSETID\u DirectSoundDevice,
DSPROPERTY\u DIRECTSOUNDDEVICE\u说明,
无效的
0,
psDirectSoundDeviceDescription,
乌尔比特斯回来了,
&乌尔比特斯回来了
);
dwWaveID=psDirectSoundDeviceDescription->WaveDeviceId;
删除[]psDirectSoundDeviceDescription;
retval=TRUE;
}
pKsPropertySet->Release();
}
返回返回;
}
HRESULT DirectSoundPrivateCreate(输出LPKSPROPERTYSET*ppKsPropertySet){
HMODULE hLibDsound=NULL;
LPFNDLLGETCLASSOBJECT pfnDllGetClassObject=NULL;
LPCLASSFACTORY pClassFactory=NULL;
LPKSPROPERTYSET pKsPropertySet=NULL;
HRESULT hr=DS_正常;
//加载dsound.dll
hLibDsound=LoadLibrary(文本(“dsound.dll”);
如果(!hLibDsound){
hr=DSERR_泛型;
}
//查找DllGetClassObject
如果(成功(hr)){
pfnDllGetClassObject=
(LPFNDLLGETCLASSOBJECT)GetProcAddress(hLibDsound,“DllGetClassObject”);
if(!pfnDllGetClassObject){
hr=DSERR_泛型;
}
}
//创建类工厂对象
如果(成功(hr)){
hr=pfnDllGetClassObject(CLSID_DirectSoundPrivate、IID_IClassFactory、(LPVOID*)和pClassFactory);
}
//创建DirectSoundPrivate对象并查询IKsPropertySet
//接口
如果(成功(hr)){
hr=pClassFactory->CreateInstance(NULL,IID_IKsPropertySet,(LPVOID*)和pKsPropertySet);
}
//释放类工厂
if(pClassFactory){
pClassFactory->Release();
}
//处理最后的成功或失败
如果(成功(hr)){
*ppKsPropertySet=pKsPropertySet;
}else if(pKsPropertySet){
pKsPropertySet->Release();
}
免费图书馆(hLibDsound);
返回人力资源;
}
BOOL回调DSEnumCallback(
LPGUID LPGUID,
LPCTSTR lpcstrDescription,
LPCTSTR LPCSTRMODEL,
LPVOID lpContext
) {
LPWSTR psz=NULL;
StringFromCLSID(*lpGuid,&psz);
德沃德韦维德
HRESULT hr = NULL;
hr = CoInitialize(NULL);
if( FAILED(hr) ) {
printf("Failed to initialize COM");
return -1;
}