Get the full audio device name from Windows

2019-01-26 14:09发布

问题:

Is there a way to get the full audio device name in Windows XP and later?

I can use MIXERCAPS but the szPname member will limit to 32 characters (including NULL). For an audio device name of "Microphone (High Definition Audio Device)", I only get back "Microphone (High Definition Aud". This is due to MAXPNAMELEN being defined to 32. I have tried redefining it to a larger number to no effect.

Here is the code I am using:

MIXERCAPS mc;
ZeroMemory( &mc, sizeof(MIXERCAPS) );
mm = mixerGetDevCaps( reinterpret_cast<UINT_PTR>(m_hMixer), &mc, sizeof(MIXERCAPS) );

I saw this question, but it references Vista and later.

回答1:

If you use the classic Windows Multimedia interface you probably can't get around the MAXPNAMELEN limitation, since that's compiled into Windows itself.

However you might be able to get the full device name if you use DirectSound instead. The following code is untested but I think it should work.

BOOL CALLBACK EnumCallback(LPGUID guid, LPCSTR descr, LPCSTR modname, LPVOID ctx)
{
    std::vector<std::string> *names = (std::vector<std::string>*)ctx;
    names->push_back(std::string(descr));
    return TRUE;
}

int main()
{
    std::vector<std::string> names;
    if (!FAILED(DirectSoundEnumerate(&EnumCallback, &names)))
    {
        // do stuff
    }
}


回答2:

You could try using devcon. Available at Microsoft's site here.

I think devcon listclass media may give you the result you're looking for.



回答3:

Below is my (Delphi) code:

This is using DirectShow/ActiveX, It enumurates DirectSound devices, which include wrapped WaveOut devices as well.

procedure EnumAudioDevices;
var
  dsCreateDevEnum  : ICreateDevEnum;
  EnumDevice       : IEnumMoniker;
  DeviceMoniker    : IMoniker;
  Data             : Integer;
  DevicePropBag    : IPropertyBag;
  DeviceName       : OLEVariant;
  I                : Integer;
begin
  // CLSID_CQzFilterClassManager = Entire DirectShow Filter List
  If CoCreateInstance(CLSID_SystemDeviceEnum,nil,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,dsCreateDevEnum) = S_OK then
  Begin
    If dsCreateDevEnum.CreateClassEnumerator(CLSID_AudioRendererCategory,EnumDevice,0) = S_OK then
    Begin
      I := 0;
      EnumDevice.Reset;
      While EnumDevice.Next(1,DeviceMoniker,@Data) = S_OK do
      Begin
        If DeviceMoniker.BindToStorage(nil,nil,IID_IPropertyBag,DevicePropBag) = NOERROR then
        Begin
          If DevicePropBag.Read('FriendlyName',DeviceName,nil) = NOERROR then
          Begin
            // Success
            ShowMessage(DeviceName);
            Inc(I);
          End;
          DevicePropBag := nil;
        End;
        DeviceMoniker := nil;
      End;
      EnumDevice := nil;
    End;
    dsCreateDevEnum := nil;
  End;
End;