Einzelnen Beitrag anzeigen

Benutzerbild von Mazel
Mazel

Registriert seit: 11. Nov 2005
Ort: Leipzig
831 Beiträge
 
#1

Win7 Audioendgerärte über EnumAudioEndpoints ermitteln

  Alt 9. Jun 2011, 19:08
Guten Abend,

seit ein paar Tagen beschäftige ich mich damit, die Audioendgeräte unter Win7 zu ermitteln und aufzulisten. Grund dafür ist, das ich versuchen möchte, eine Anwendung zu schreiben, mit der ich das Standardausgabegerät ändern kann - von den Boxen schnell zu den Kopfhörern wechseln und umgegehrt.

Nun habe ich über zahlreiche Seiten Informationen bekommen, doch leider schaff ich es nicht die Geräte aufzulisten auch nicht aufzuzählen. Probleme machen mir manche Deklarationen die in der MSDN wohl anders sind als die Übersetzung die ich habe, mit den doppelten Pointer komm ich noch nicht ganz klar.

zunächst folgende Links und Codeblöcke:
http://msdn.microsoft.com/en-us/libr...=VS.85%29.aspx
http://msdn.microsoft.com/en-us/libr...=VS.85%29.aspx
http://msdn.microsoft.com/en-us/libr...=VS.85%29.aspx

Code:
unit Unit2;

interface

uses
  Windows, ActiveX, ComObj;

const
  CLSID_MMDeviceEnumerator            : TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
  IID_IMMDeviceEnumerator              : TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
  IID_IMMDevice                        : TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
  IID_IMMDeviceCollection              : TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
  IID_IAudioEndpointVolume             : TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';
  IID_IAudioMeterInformation           : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
  IID_IAudioEndpointVolumeCallback     : TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';

  DEVICE_STATE_ACTIVE                  = $00000001;
  DEVICE_STATE_UNPLUGGED               = $00000002;
  DEVICE_STATE_NOTPRESENT              = $00000004;
  DEVICE_STATEMASK_ALL                 = $00000007;

type
  EDataFlow = TOleEnum;

const
  eRender                              = $00000000;
  eCapture                             = $00000001;
  eAll                                 = $00000002;
  EDataFlow_enum_count                 = $00000003;

type
  ERole = TOleEnum;

const
  eConsole                             = $00000000;
  eMultimedia                          = $00000001;
  eCommunications                      = $00000002;
  ERole_enum_count                     = $00000003;

type
  IAudioEndpointVolumeCallback = interface(IUnknown)
  ['{657804FA-D6AD-4496-8A60-352752AF4F89}']
  end;

  IAudioEndpointVolume = interface(IUnknown)
  ['{5CDF2C82-841E-4546-9722-0CF74078229A}']
    function RegisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    function UnregisterControlChangeNotify(AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
    function GetChannelCount(out PInteger): Integer; stdcall;
    function SetMasterVolumeLevel(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;
    function SetMasterVolumeLevelScalar(fLevelDB: single; pguidEventContext: PGUID): Integer; stdcall;
    function GetMasterVolumeLevel(out fLevelDB: single): Integer; stdcall;
    function GetMasterVolumeLevelScaler(out fLevelDB: single): Integer; stdcall;
    function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
    function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: PGUID): Integer; stdcall;
    function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double): Integer; stdcall;
    function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double): Integer; stdcall;
    function SetMute(bMute: Boolean; pguidEventContext: PGUID): Integer; stdcall;
    function GetMute(out bMute: Boolean): Integer; stdcall;
    function GetVolumeStepInfo(pnStep: Integer; out pnStepCount: Integer): Integer; stdcall;
    function VolumeStepUp(pguidEventContext: PGUID): Integer; stdcall;
    function VolumeStepDown(pguidEventContext: PGUID): Integer; stdcall;
    function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
    function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;
  end;

  IAudioMeterInformation = interface(IUnknown)
  ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']
    function GetPeakValue(out Peak: Real): HRESULT; stdcall;
  end;

  IPropertyStore = interface(IUnknown)
  end;

  IMMDevice = interface(IUnknown)
  ['{D666063F-1587-4E43-81F1-B948E807363F}']
    function Activate(const refId: TGUID;
                      dwClsCtx: DWORD;
                      pActivationParams: PInteger;
                      out pEndpointVolume: IAudioEndpointVolume): Hresult; stdCall;
    function OpenPropertyStore(stgmAccess: DWORD; out ppProperties: IPropertyStore): Hresult; stdcall;
    function GetId(out ppstrId: PLPWSTR): Hresult; stdcall;
    function GetState(out State: Integer): Hresult; stdcall;
  end;

  IMMDeviceCollection = interface(IUnknown)
  ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
    function GetCount(out pcDevices: UINT): HRESULT; stdcall;
    function Item(nDevice: UINT; out ppDevice: IMMDevice): HRESULT; stdcall;
  end;

  IMMNotificationClient = interface(IUnknown)
  ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
  end;

  IMMDeviceEnumerator = interface(IUnknown)
  ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
    function EnumAudioEndpoints(dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection: IMMDeviceCollection): Hresult; stdcall;
    function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult; stdcall;
    function GetDevice(pwstrId: pointer; out Dev: IMMDevice): HResult; stdcall;
    function RegisterEndpointNotificationCallback(pClient: IMMNotificationClient): Hresult; stdcall;
  end;

implementation

end.
Über folgenden Abschnitt versuche ich anhand der oben genannten Informationen die Geräte auszulesen bzw. aufzuzählen:
Code:
procedure TForm1.Button2Click(Sender: TObject);
var
  MMDeviceCollection: IMMDeviceCollection;
  MMDeviceEnumerator: IMMDeviceEnumerator;
  hr: HResult;
  count : UINT;

begin
  hr := CoCreateInstance(CLSID_MMDeviceEnumerator, nil, CLSCTX_ALL, IID_IMMDeviceEnumerator, MMDeviceEnumerator);
  hr := MMDeviceEnumerator.EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, MMDeviceCollection);
  // Ungültiger Zeiger
  ShowMessage(SysErrorMessage(hr));
  // führt zum Programmabbruch - Lesen von Adresse 00000000 ...
  hr := MMDeviceCollection.GetCount(count);
end;
Das Problem ist, das durch EnumAudioEndpoints ein Fehler mit der MMDeviceCollection vorliegt, hr von CoCreateInstance ist 0.

Im dritten Link zur MSDN wird aber im CoCreateInstance mit einem void** gearbeitet, was mir erstmal nicht viel sagt.

Weiterhin werden für die IMMDevice... Pointer deklariert, was aber laut Delphideklaration nicht der Fall ist, funktionieren tu es aber bis zum genannten Punkt dennoch.

Hat jemand einen Rat oder einen Ansatz, damit ich die Ausgabegeräte ermitteln und am Ende auch über die Anwendung setzen kann?

Grüße
Marcel
Marcel Jänicke
www.mj-software.net
  Mit Zitat antworten Zitat