在应用程序中,如果用户使用默认的输出设备来输出声音,那么咱就没有必要来枚举所有的输出设备了。但是,当应用程序并不支持所有的输出设备,或者程序中需要两个或多个设备的时候或需要用户自己来选择设备的时候,咱就要枚举各个设备了。
枚举设备,首先,需要定义一个回调函数,该回调函数可以被系统中的每个设备来调用,该函数的命名没有限制,但是函数的声明方式必须是DSEnumCallBack为原型,该类型的样式在Delphi中为:
function DsEnumProc(lpGuid: PGUID; lpcstrDescription, lpcstrModule: PAnsiChar;
lpContext: Pointer): BOOL;stdcall;
该函数被作为参数传递给枚举设备的函数 DirectSoundEnumerate,该函数的原型在Delphi中声明样式为:
function DirectSoundEnumerate(lpDSEnumCallback: TDSEnumCallback; lpContext: Pointer): HResult;
stdcall; external DirectSoundDLL name 'DirectSoundEnumerateA';
第一个参数,TDSEnumCallBack就是上面给出的那个回调函数的样式了。第二个参数为任何一个你想要传入的东西的指针。
函数返回类型HResult,可以通过Succeeded来判断函数是否调用成功。
咱们在使用DirectSoundEnumerate函数的时候,可以想象该函数的实现方式,肯定是带有一个循环的,每枚举到一个设备的时候,会调用一次咱给的回调函数DsEnumCallBack,那么该回调函数在调用的过程中,如果该回调函数返回True,那么DirectSoundEnumerate就会继续下一次枚举,直到所有的设备都被枚举,函数返回,否则,只要咱给该回调函数返回False,那么DirectSoundEnumerate就不继续下一次枚举(不管设备是否全部枚举完成),而直接返回。
这里给一个枚举设备的例子,本例子中,将所有枚举到的设备都添加到Combobox中,将设备的GUID也保存在Combobox中,代码如下:
function DsEnumProc(lpGuid: PGUID; lpcstrDescription, lpcstrModule: PAnsiChar;lpContext: Pointer): BOOL;stdcall;
var
tempGuid: PGUID;
begin
Result := True;
if lpGuid <> nil then
begin
tempGuid := GetMemory(SizeOf(TGUID));
if tempGuid = nil then
begin
Result := true;
exit;
end;
CopyMemory(tempGuid,lpGuid,SizeOf(TGuid));
//这里的lpContext就是咱在DirectSoundEnumerate函数中传递的Combobox,所以直接转化就好了
TComboBox(lpContext).Items.AddObject(string(lpcstrDescription),TObject(tempGuid));
//不要主声音驱动程序
end;
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
DirectSoundEnumerate(DsEnumProc,self.ComboBox1);
end;
上面给讲的是枚举输出设备,自然DirectSound也提供枚举输入设备(录音设备)的,操作方式都一样,只是枚举函数名称不同而已,输出设备的枚举函数为:
DirectSoundCaptureEnumerate
所以,枚举输入设备,咱们只用按照上面的代码将 DirectSoundEnumerate
换成DirectSoundCaptureEnumerate,其他不变,则可