修改正确的MMDevApi.pas

xiaoxiao2021-02-28  49

unit MMDevApi; {$MINENUMSIZE 4} {$WEAKPACKAGEUNIT} interface uses  Windows, ActiveX, ComObj, propsys, mmsystem,  Winapi.Messages, System.SysUtils, System.Variants, System.Classes; const  CLASS_IMMDeviceEnumerator: 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}';  // undocumented  IID_IRemoteAudioSession: TGUID = '{33969B1D-D06F-4281-B837-7EAAFD21A9C0}';  IID_IAudioSessionQuerier: TGUID = '{94BE9D30-53AC-4802-829C-F13E5AD34776}';  IID_IAudioSessionQuery: TGUID = '{94BE9D30-53AC-4802-829C-F13E5AD34775}';  //  IID_IAudioSessionEvents: TGUID = '{24918ACC-64B3-37C1-8CA9-74A66E9957A8}';  IID_IAudioSessionControl: TGUID = '{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}';  IID_ISimpleAudioVolume: TGUID = '{87CE5498-68D6-44E5-9215-6DA47EF883D8}';  IID_IAudioSessionManager: TGUID = '{BFA971F1-4D5E-40BB-935E-967039BFBEE4}';  IID_IAudioClient: TGUID = '{1CB9AD4C-DBFA-4c32-B178-C2F568A703B2}';  IID_IAudioRenderClient: TGUID = '{F294ACFC-3146-4483-A7BF-ADDCA7C260E2}';  DEVICE_STATE_ACTIVE = $00000001;  DEVICE_STATE_DISABLE = $00000002;  DEVICE_STATE_NOTPRESENT = $00000004;  DEVICE_STATE_UNPLUGGED = $00000008;  DEVICE_STATEMASK_ALL = $0000000F;  // QueryHardwareSupport  ENDPOINT_HARDWARE_SUPPORT_VOLUME = $00000001;  ENDPOINT_HARDWARE_SUPPORT_MUTE = $00000002;  ENDPOINT_HARDWARE_SUPPORT_METER = $00000004; type  EDataFlow = TOleEnum; type AUDCLNT_SHAREMODE =(   AUDCLNT_SHAREMODE_SHARED,   AUDCLNT_SHAREMODE_EXCLUSIVE ); type REFIID =( IID_IAudioCaptureClient,IID_IAudioClock,//IID_IAudioSessionControl, IID_IAudioRenderClient, IID_IAudioStreamVolume,IID_IChannelAudioVolume,IID_IMFTrustedOutput ) ;   //,IID_ISimpleAudioVolume const  eRender = $00000000;  eCapture = $00000001;  eAll = $00000002;  EDataFlow_enum_count = $00000003; type  ERole = TOleEnum; type  REFERENCE_TIME=LONGLONG; const  eConsole = $00000000;  eMultimedia = $00000001;  eCommunications = $00000002;  ERole_enum_count = $00000003;  // AudioSessionState  AudioSessionStateInactive = 0;  AudioSessionStateActive = 1;  AudioSessionStateExpired = 2;  // AudioSessionDisconnectReason  DisconnectReasonDeviceRemoval = 0;  DisconnectReasonServerShutdown = DisconnectReasonDeviceRemoval + 1;  DisconnectReasonFormatChanged = DisconnectReasonServerShutdown + 1;  DisconnectReasonSessionLogoff = DisconnectReasonFormatChanged + 1;  DisconnectReasonSessionDisconnected = DisconnectReasonSessionLogoff + 1;  DisconnectReasonExclusiveModeOverride = DisconnectReasonSessionDisconnected + 1; type  PAUDIO_VOLUME_NOTIFICATION_DATA = ^AUDIO_VOLUME_NOTIFICATION_DATA;  AUDIO_VOLUME_NOTIFICATION_DATA = packed record   guidEventContext: TGUID;   bMuted: BOOL;   fMasterVolume: Single;   nChannels: UINT;   afChannelVolumes: array[1..1] of Single;  end; // type pp= ^pWAVEFORMATEX;  已测试,不能用 type  IAudioRenderClient = interface(IUnknown) ['{F294ACFC-3146-4483-A7BF-ADDCA7C260E2}']     function GetBuffer(const NumFramesRequested: UINT; out ppData: PByte): HResult; stdcall;     function ReleaseBuffer(const NumFramesWritten: UINT32; const dwFlags: DWord): HResult; stdcall; end;  IAudioClient = interface(IUnknown)   ['{1CB9AD4C-DBFA-4c32-B178-C2F568A703B2}']          function Initialize(ShareMode: AUDCLNT_SHAREMODE; StreamFlags: Dword;        hnsBufferDuration: REFERENCE_TIME; hnsPeriodicity: REFERENCE_TIME;     pFormat: PWaveFormatEx; AudioSessionGuid: IUnknown): HResult; stdcall;       //LPCGUID     function GetBufferSize(out pNumBufferFrames: UINT32): HResult; stdcall;     function GetStreamLatency(out phnsLatency: REFERENCE_TIME): HResult; stdcall;     function GetCurrentPadding(out pNumPaddingFrames: UINT32): HResult; stdcall;     function IsFormatSupported(ShareMode: AUDCLNT_SHAREMODE; pFormat: PWaveFormatEx; out ppClosestMatch: PWaveFormatEx): HResult; stdcall;     function GetMixFormat(out ppDeviceFormat: PWaveFormatEx): HResult; stdcall;     function GetDevicePeriod(out phnsDefaultDevicePeriod: REFERENCE_TIME; phnsMinimumDevicePeriod: REFERENCE_TIME): HResult; stdcall;     function Start(): HResult; stdcall;     function Stop(): HResult; stdcall;     function Reset(): HResult; stdcall;     function SetEventHandle(const eventHandle: pHANDLE): HResult; stdcall;  //org:HANDLE     function GetService(const riid: TGUID; out ppv: Pointer): HResult; stdcall;       end;  IAudioEndpointVolumeCallback = interface(IUnknown)   ['{657804FA-D6AD-4496-8A60-352752AF4F89}']   function OnNotify(pNotify: PAUDIO_VOLUME_NOTIFICATION_DATA): HRESULT; stdcall;  end;  IAudioEndpointVolume = interface(IUnknown)   ['{5CDF2C82-841E-4546-9722-0CF74078229A}']   function RegisterControlChangeNotify(pNotify: IAudioEndpointVolumeCallback): HRESULT; stdcall;   function UnregisterControlChangeNotify(pNotify: IAudioEndpointVolumeCallback): HRESULT; stdcall;   function GetChannelCount(var pnChannelCount: uint): HRESULT; stdcall;   function SetMasterVolumeLevel(fLevelDB: Single; pguidEventContext: PGuid): HRESULT; stdcall;   function SetMasterVolumeLevelScalar(fLevel: Single; pguidEventContext: PGuid): HRESULT; stdcall;   function GetMasterVolumeLevel(var pfLevelDB: Single): HRESULT; stdcall    ;   function GetMasterVolumeLevelScalar(var pfLevel: Single): HRESULT; stdcall;   function SetChannelVolumeLevel(nChannel: uint; fLevelDB: Single; pguidEventContext: PGuid): HRESULT; stdcall;   function SetChannelVolumeLevelScalar(nChannel: uint; fLevel: Single; pguidEventContext: PGuid): HRESULT; stdcall ;   function GetChannelVolumeLevel(nChannel: uint; fLevelDB: Single): HRESULT; stdcall;   function GetChannelVolumeLevelScalar(nChannel: uint; fLevel: Single): HRESULT; stdcall;   function SetMute(bMute: bool; pguidEventContext: PGuid): HRESULT; stdcall;   function GetMute(var pbMute: bool): HRESULT; stdcall;   function GetVolumeStepInfo(var pnStep: uint; var pnStepCount: uint): HRESULT; stdcall;   function VolumeStepUp(pguidEventContext: PGuid): HRESULT; stdcall;   function VolumeStepDown(pguidEventContext: PGuid): HRESULT; stdcall;   function QueryHardwareSupport(var pdwHardwareSupportMask: uint): HRESULT; stdcall;   function GetVolumeRange(var pflVolumeMindB: Single; var pflVolumeMaxdB: Single;    var pflVolumeIncrementdB: Single): HRESULT; stdcall;  end;  IAudioMeterInformation = interface(IUnknown)   ['{C02216F6-8C67-4B5B-9D00-D008E73E0064}']   function GetPeakValue(out pfPeak: Single): HResult; stdcall;   function GetMeteringChannelCount(out pnChannelCount: uint): HResult; stdcall;   function GetChannelsPeakValues(u32ChannelCount: uint; afPeakValues: pSingle): HResult; stdcall;   function QueryHardwareSupport(out pdwHardwareSupportMask: uint): HResult; stdcall;  end;  IMMDevice = interface(IUnknown)   ['{D666063F-1587-4E43-81F1-B948E807363F}']   function Activate(const iid: TGUID; dwClsCtx: uint; pActivationParams: PPropVariant; out ppInterface: IUnknown): HRESULT; stdcall;   function OpenPropertyStore(stgmAccess: integer; out ppProperties: IPropertyStore): HRESULT; stdcall;   function GetId(ppstrId: PWChar): HRESULT; stdcall;   function GetState(var pdwState: uint): HRESULT; stdcall;  end;  IMMDeviceCollection = interface(IUnknown)   ['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']   function GetCount(var pcDevices: uint): HRESULT; stdcall;   function Item(nDevice: uint; out ppDevice: IMMDevice): HRESULT; stdcall;  end;  //IMMNotificationClient = interface(IUnknown)  // ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']  //end;  IMMNotificationClient = interface(IUnknown) ['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']   function OnDeviceStateChanged(const pwstrDeviceId: LPCWSTR;                                   const dwNewState: DWord): HRESULT; stdcall;     // Parameters     // pwstrDeviceId [in]     //  Pointer to the endpoint ID string that identifies the audio endpoint device.     //  This parameter points to a null-terminated, wide-character string containing the endpoint ID.     //  The string remains valid for the duration of the call.     // dwNewState [in]     //  Specifies the new state of the endpoint device.     //  The value of this parameter is one of the following DEVICE_STATE_XXX constants:     //    DEVICE_STATE_ACTIVE     //    DEVICE_STATE_DISABLED     //    DEVICE_STATE_NOTPRESENT     //    DEVICE_STATE_UNPLUGGED function OnDeviceAdded(const pwstrDeviceId: LPCWSTR): HRESULT; stdcall;     // The OnDeviceAdded method indicates that a new audio endpoint device has been added.     // Parameters     //   pwstrDeviceId [in]     //   Pointer to the endpoint ID string that identifies the audio endpoint device.     //   This parameter points to a null-terminated, wide-character string containing     //   the endpoint ID. The string remains valid for the duration of the call. function OnDeviceRemoved(const pwstrDeviceId: LPCWSTR): HRESULT; stdcall;   //  HRESULT OnDeviceRemoved(  [in] LPCWSTR pwstrDeviceId);     // Parameters     // flow [in]     //  The data-flow direction of the endpoint device.     //  This parameter is set to one of the following EDataFlow enumeration values:     //    - eRender     //    - eCapture     //  The data-flow direction for a rendering device is eRender.     //  The data-flow direction for a capture device is eCapture.     // role [in]     //  The device role of the audio endpoint device.     //  This parameter is set to one of the following ERole enumeration values:     //    - eConsole     //    - eMultimedia     //    - eCommunications     // pwstrDefaultDeviceId [in]     //  Pointer to the endpoint ID string that identifies the audio endpoint device.     //  This parameter points to a null-terminated, wide-character string containing the endpoint ID.     //  The string remains valid for the duration of the call.     //  If the user has removed or disabled the default device for a particular role,     //  and no other device is available to assume that role, then pwstrDefaultDeviceId is NULL. function OnDefaultDeviceChanged(const flow: EDataFlow;                                     const role: ERole;                                     const pwstrDefaultDeviceId: LPCWSTR): HRESULT; stdcall;     // The OnDefaultDeviceChanged method notifies the client that the default audio endpoint device for a particular device role has changed.     // Parameters     //   flow [in]     //    The data-flow direction of the endpoint device.     //    This parameter is set to one of the following EDataFlow enumeration values:     //     - eRender  : The data-flow direction for a rendering device is eRender.     //     - eCapture : The data-flow direction for a capture device is eCapture.     //   role [in]     //    The device role of the audio endpoint device.     //    This parameter is set to one of the following ERole enumeration values:     //    - eConsole     //    - eMultimedia     //    - eCommunications     //   pwstrDefaultDevice [in]     //    Pointer to the endpoint ID string that identifies the audio endpoint device.     //    This parameter points to a null-terminated, wide-character string containing the endpoint ID.     //    The string remains valid for the duration of the call.     //    If the user has removed or disabled the default device for a particular role,     //    and no other device is available to assume that role, then pwstrDefaultDevice is NIL.    //function OnPropertyValueChanged(const pwstrDeviceId: LPCWSTR; const key: PROPERTYKEY): HRESULT; stdcall;    function OnPropertyValueChanged(pwstrDeviceID: LPCWSTR; const key: PROPERTYKEY): HRESULT; stdcall;         // Parameters     //  pwstrDeviceId [in]     //   Pointer to the endpoint ID string that identifies the audio endpoint device.     //   This parameter points to a null-terminated, wide-character string that contains the endpoint ID.     //   The string remains valid for the duration of the call.     //  key [in]     //   A PROPERTYKEY structure that specifies the property.     //   The structure contains the property-set GUID and an index identifying a property within the set.     //   The structure is passed by value. It remains valid for the duration of the call.     //   For more information about PROPERTYKEY, see the Windows SDK documentation.     //     // Remarks     //   A call to the IPropertyStore.SetValue method that successfully changes the value of     //   a property of an audio endpoint device generates a call to OnPropertyValueChanged.     //   For more information about IPropertyStore.SetValue, see the Windows SDK documentation.     //   A client can use the key parameter to retrieve the new property value. end;  IMMDeviceEnumerator = interface(IUnknown)   ['{A95664D2-9614-4F35-A746-DE8DB63617E6}']   function EnumAudioEndpoints(dataFlow: EDataFlow; dwStateMask: DWORD; out ppDevices: IMMDeviceCollection): HRESULT; stdcall;   function GetDefaultAudioEndpoint(dataFlow: EDataFlow; role: ERole; out ppEndpoint: IMMDevice): HRESULT; stdcall;   function GetDevice(pwstrId: PWChar; out ppDevice: IMMDevice): HRESULT; stdcall;   function RegisterEndpointNotificationCallback(var pClient: IMMNotificationClient): HRESULT; stdcall;   function UnregisterEndpointNotificationCallback(var pClient: IMMNotificationClient): HRESULT; stdcall;  end;  { undocumented }  IRemoteAudioSession = interface(IUnknown)   ['{33969B1D-D06F-4281-B837-7EAAFD21A9C0}']   function func_a: HResult; stdcall;   function func_b: HResult; stdcall;   function func_c: HResult; stdcall;   function func_d: HResult; stdcall;   function func_e: HResult; stdcall;   function func_f: HResult; stdcall;   function func_g: HResult; stdcall;   function func_h: HResult; stdcall;   function func_i: HResult; stdcall;   function func_j: HResult; stdcall;   function func_k: HResult; stdcall;   function GetProcessID(out pid: uint): HResult; stdcall;  end;  { undocumented }  IAudioSessionQuerier = interface(IUnknown)   ['{94BE9D30-53AC-4802-829C-F13E5AD34776}']   function GetNumSessions(out NumSessions: uint): HResult; stdcall;   function QuerySession(Num: uint; out Session: IUnknown): HResult; stdcall;  end;  { undocumented }  IAudioSessionQuery = interface(IUnknown)   ['{94BE9D30-53AC-4802-829C-F13E5AD34775}']   function GetQueryInterface(out AudioQuerier: IAudioSessionQuerier): HResult; stdcall;  end;  IAudioSessionEvents = interface(IUnknown)   ['{24918ACC-64B3-37C1-8CA9-74A66E9957A8}']   function OnDisplayNameChanged(NewDisplayName: LPCWSTR; EventContext: pGuid): HResult; stdcall;   function OnIconPathChanged(NewIconPath: LPCWSTR; EventContext: pGuid): HResult; stdcall;   function OnSimpleVolumeChanged(NewVolume: Single; NewMute: LongBool; EventContext: pGuid): HResult; stdcall;   function OnChannelVolumeChanged(ChannelCount: uint; NewChannelArray: PSingle; ChangedChannel: uint;    EventContext: pGuid): HResult; stdcall;   function OnGroupingParamChanged(NewGroupingParam, EventContext: pGuid): HResult; stdcall;   function OnStateChanged(NewState: uint): HResult; stdcall; // AudioSessionState   function OnSessionDisconnected(DisconnectReason: uint): HResult; stdcall; // AudioSessionDisconnectReason  end;  IAudioSessionControl = interface(IUnknown)   ['{F4B1A599-7266-4319-A8CA-E70ACB11E8CD}']   function GetState(out pRetVal: uint): HResult; stdcall;   function GetDisplayName(out pRetVal: LPWSTR): HResult; stdcall; // pRetVal must be freed by CoTaskMemFree   function SetDisplayName(Value: LPCWSTR; EventContext: pGuid): HResult; stdcall;   function GetIconPath(out pRetVal: LPWSTR): HResult; stdcall; // pRetVal must be freed by CoTaskMemFree   function SetIconPath(Value: LPCWSTR; EventContext: pGuid): HResult; stdcall;   function GetGroupingParam(pRetVal: pGuid): HResult; stdcall;   function SetGroupingParam(OverrideValue, EventContext: pGuid): HResult; stdcall;   function RegisterAudioSessionNotification(const NewNotifications: IAudioSessionEvents): HResult; stdcall;   function UnregisterAudioSessionNotification(const NewNotifications: IAudioSessionEvents): HResult; stdcall;  end;  ISimpleAudioVolume = interface(IUnknown)   ['{87CE5498-68D6-44E5-9215-6DA47EF883D8}']   function SetMasterVolume(fLevel: Single; EventContext: pGuid): HResult; stdcall;   function GetMasterVolume(out fLevel: Single): HResult; stdcall;   function SetMute(bMute: LongBool; EventContext: pGuid): HResult; stdcall;      function GetMute(out bMute: LongBool): HResult; stdcall;  end;  IAudioSessionManager = interface(IUnknown)   ['{BFA971F1-4D5E-40BB-935E-967039BFBEE4}']   function GetAudioSessionControl(AudioSessionGuid: pGUID; StreamFlag: uint;    out SessionControl: IAudioSessionControl): HResult; stdcall;   function GetSimpleAudioVolume(AudioSessionGuid: pGuid; StreamFlag: uint;    out AudioVolume: ISimpleAudioVolume): HResult; stdcall;  end; // get ISimpleAudioVolume from ProcessID function GetSimpleAudioVolumeFromPid(const AudioDevice: IMMDevice; pid: uint; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; // get ISimpleAudioVolume from Process Handle function GetSimpleAudioVolumeFromHandle(const AudioDevice: IMMDevice; Hnd: uint; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; // function GetSimpleAudioVolumeFromModuleName(const AudioDevice: IMMDevice; ModuleName: pWideChar; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; implementation uses tlhelp32; function GetProcessIdFromModuleName(ModuleName: pWideChar): LongWord; var  ToolSnap: LongWord;  ProcessEntry: ProcessEntry32W;  bCont: LongBool;  ModuleName16: WideString; begin  Result := 0;  ModuleName16 := ModuleName;  ToolSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  ProcessEntry.dwSize := sizeof(ProcessEntry);  bCont := Process32FirstW(ToolSnap, ProcessEntry);  while bCont do begin   if ProcessEntry.szExeFile = ModuleName16 then    Result := ProcessEntry.th32ProcessID;   ProcessEntry.dwSize := sizeof(ProcessEntry);   bCont := (Result = 0) and Process32NextW(ToolSnap, ProcessEntry);  end;  CloseHandle(ToolSnap); end; function GetSimpleAudioVolumeFromModuleName(const AudioDevice: IMMDevice; ModuleName: pWideChar; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; var  pid: LongWord; begin  pid := GetProcessIdFromModuleName(ModuleName);  Result := GetSimpleAudioVolumeFromPid(AudioDevice, pid, SimpleAudio, currguid); end; function GetSimpleAudioVolumeFromHandle(const AudioDevice: IMMDevice; Hnd: uint; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; var  pid: uint; begin  GetWindowThreadProcessId(Hnd, pid);  Result := GetSimpleAudioVolumeFromPid(AudioDevice, pid, SimpleAudio, currguid); end; function GetSimpleAudioVolumeFromPid(const AudioDevice: IMMDevice; pid: uint; out SimpleAudio: ISimpleAudioVolume; out currguid: tguid): Boolean; stdcall; var  SessionManager: IAudioSessionManager;  SessionQuery: IAudioSessionQuery;  SessionQuerier: IAudioSessionQuerier;  RemoteSession: IRemoteAudioSession;  SessionControl: IAudioSessionControl;  dummy: IUnknown;  MaxSession, Sessionpid: uint;  hr, i: Integer; begin  Result := False;  SessionManager := nil;  SessionQuery := nil;  SessionQuerier := nil;  SessionControl := nil;  // get AudioSessionManager  hr := AudioDevice.Activate(IID_IAudioSessionManager, CLSCTX_ALL, nil, IUnknown(SessionManager));  if Succeeded(hr) then begin   // get SessionQuery   hr := SessionManager.QueryInterface(IID_IAudioSessionQuery, SessionQuery);   if Succeeded(hr) then begin    // get SessionQuerier    hr := SessionQuery.GetQueryInterface(SessionQuerier);    if Succeeded(hr) then begin    // check sessions    hr := SessionQuerier.GetNumSessions(MaxSession);    if Succeeded(hr) then     if MaxSession > 0 then      for i := 0 to MaxSession - 1 do begin       dummy := nil;       hr := SessionQuerier.QuerySession(i, dummy);       RemoteSession := nil;       if Succeeded(hr) then begin       // get RemoteSession       hr := dummy.QueryInterface(IID_IRemoteAudioSession, RemoteSession);       if Succeeded(hr) then begin        // compare ProcessID        if Succeeded(RemoteSession.GetProcessID(Sessionpid)) then         if Sessionpid <> 0 then          if Sessionpid = pid then begin          Result := Succeeded(RemoteSession.QueryInterface(IID_ISimpleAudioVolume, SimpleAudio));          if Succeeded(dummy.QueryInterface(IID_IAudioSessionControl, SessionControl)) then           SessionControl.GetGroupingParam(@currguid);          SessionControl := nil;          end;        if Result then         Break;       end;       end;      end;    RemoteSession := nil;    SessionQuerier := nil;    end;    SessionQuery := nil;   end;   SessionManager := nil;  end; end; end.
转载请注明原文地址: https://www.6miu.com/read-2625439.html

最新回复(0)