Author Topic: WASAPI device icons  (Read 389 times)

3delite

  • Posts: 895
WASAPI device icons
« on: 12 Jan '17 - 07:34 »
Hi!

Is there a way to get the WASAPI audio device icons?



The following code seems working when querying 'PKEY_Device_FriendlyName', returns the same string as BASS gives, but 'PKEY_AudioEndpointLogo_IconPath' always returns nil:

Code: [Select]
function TFormMain.GetWASAPIIcon(DeviceID: String): String;
var
    MMDeviceEnumerator: IMMDeviceEnumerator;
    MMDevice: IMMDevice;
    HR: HResult;
    PropertyStore: IPropertyStore;
    pv: PROPVARIANT;
begin
    Result := '';

    if CheckWin32Version(6, 0) then begin// The Core Audio APIs were introduced in Windows Vista.

        HR := CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL,
          IMMDeviceEnumerator, MMDeviceEnumerator);
        if Failed(HR) then
          Exit;

        HR := MMDeviceEnumerator.GetDevice(PChar(DeviceID), MMDevice);
        if Failed(HR) then
          Exit;

        HR := MMDevice.OpenPropertyStore(STGM_READ, PropertyStore);
        if Failed(HR) then
          Exit;

        // Initialize container for property value.
        PropVariantInit(pv);

        HR := PropertyStore.GetValue(PKEY_AudioEndpointLogo_IconPath, pv);
        if Failed(HR) then
          Exit;

        Result := pv.pwszVal;

        PropVariantClear(pv);

    end;
end;

Any suggestions?

Thank you!

EWeiss

  • Posts: 342
Re: WASAPI device icons
« Reply #1 on: 12 Jan '17 - 15:52 »
i can only see the IconPath is called from IAudioSessionControl
will return 0 on IMMDevice

Code: [Select]
   PKEY_AudioEndpointLogo_IconPath: TPropertyKey = (
                fmtid: (D1:$f1ab780d; D2:$2010; D3: $4ed3;
                D4: ($a3, $a6, $8b, $87, $f0, $f0, $c4, $76));
                pid: 1);

Code: [Select]
    PropVariantInit(AudioEndpointLogo);
    HR := propertyStore.GetValue(PKEY_AudioEndpointLogo_IconPath, AudioEndpointLogo);
    if HR <> S_OK then
      raise Exception.Create('Unable to retrieve IconPath !');

    if AudioEndpointLogo.vt = VT_LPWSTR  then
    begin
      LogoPath := @LogoPathBuf[0];
{$IFDEF UNICODE}
      StrCopy(LogoPath, AudioEndpointLogo.pwszVal);
{$ELSE}
      StrCopyW(LogoPath, AudioEndpointLogo.pwszVal, 127);
{$ENDIF}
      Result.LogoPath := LogoPath;
    end;

greets

3delite

  • Posts: 895
Re: WASAPI device icons
« Reply #2 on: 12 Jan '17 - 20:15 »
Tried to query with IAudioSessionControl but I still get empty string always.

If you managed to get the icon path, please share your code! It would be helpful.

Code: [Select]
function TFormMain.GetWASAPIIcon(DeviceID: String): String;
var
    MMDeviceEnumerator: IMMDeviceEnumerator;
    MMDevice: IMMDevice;
    HR: HResult;
    PropertyStore: IPropertyStore;
    pv: PROPVARIANT;
    AudioSessionControl: IAudioSessionControl;
    MMDeviceCollection: IMMDeviceCollection;
    DeviceCount: Cardinal;
    IDStr: PChar;
    i: Integer;
    AudioSessionManager: IAudioSessionManager;
    IconPath: PChar;
begin
    Result := '';

    if CheckWin32Version(6, 0) then begin// The Core Audio APIs were introduced in Windows Vista.

        HR := CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL, IMMDeviceEnumerator, MMDeviceEnumerator);
        if Failed(HR) then
          Exit;

        HR := MMDeviceEnumerator.EnumAudioEndpoints(eAll, DEVICE_STATEMASK_ALL, MMDeviceCollection);
        if Failed(HR) then
          Exit;

       MMDeviceCollection.GetCount(DeviceCount);

       for i := 0 to DeviceCount - 1 do begin

            MMDeviceCollection.Item(i, MMDevice);

            MMDevice.GetId(IDStr);

            if String(IDStr) = DeviceID then begin

                MMDevice.Activate(IID_IAudioSessionManager, CLSCTX_ALL, nil, AudioSessionManager);

                AudioSessionManager.GetAudioSessionControl(@IID_IAudioSessionControl, 0, AudioSessionControl);

                AudioSessionControl.GetIconPath(IconPath);

                Result := IconPath;

                Break;

            end;

       end;

    end;
end;

Thanks!

EWeiss

  • Posts: 342
Re: WASAPI device icons
« Reply #3 on: 13 Jan '17 - 10:08 »
i think you can not get the Icon Path if your use a 32Bit application.
do not forgot the Dialog for Sound under W7 64Bit come from a  64 Bit DLL (i think)
test it with a 64Bit Application.
i hope it work then.

greets

everson.clei

  • Posts: 22
Re: WASAPI device icons
« Reply #4 on: 13 Jan '17 - 11:22 »
Hello,

3delite, try to download the example of this link (http://www.delphipraxis.net/183977-wasapi-loopback-audio-capturing.html ) where it has a class (MMDevApi.pas) and there are the methods:

  IAudioSessionControl = interface(IUnknown)
  ['{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}']
   function GetIconPath(out pRetVal: LPWSTR): HResult; stdcall; // pRetVal must be freed by CoTaskMemFree
   function SetIconPath(Value: LPCWSTR; EventContext: pGuid): HResult; stdcall;

I have not tested the codes, but maybe these methods should help you recover the icons!   

greetings

3delite

  • Posts: 895
Re: WASAPI device icons
« Reply #5 on: 13 Jan '17 - 14:12 »
Tested both functions built to Win64, still both just return an empty string always.

Tried the unit from the link, no change. Although I was using MfPack, seems to be more complete.

It would be cool if a variable 'IconPath: PWideChar' would be added to BASS_WASAPI_DEVICEINFO structure. It would be useful if it is possible at all to get the icon path somehow. :-\

Thanks for helping so far!