i want to adjust the volume programatically like Get/SetMasterVolume in vista and xp? using mmsystem unit?
Sebastian Oliva
Here's the implementation of a general purpose api for audio: MMDevApi
and an example with a button
unit Unit33;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, MMDevApi, ActiveX, StdCtrls;
type
TForm33 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form33: TForm33;
endpointVolume: IAudioEndpointVolume = nil;
implementation
{$R *.dfm}
procedure TForm33.Button1Click(Sender: TObject);
var
VolumeLevel: Single;
begin
if endpointVolume = nil then Exit;
VolumeLevel := 0.50;
endpointVolume.SetMasterVolumeLevelScalar(VolumeLevel, nil);
Caption := Format('%1.8f', [VolumeLevel])
end;
procedure TForm33.FormCreate(Sender: TObject);
var
deviceEnumerator: IMMDeviceEnumerator;
defaultDevice: IMMDevice;
begin
CoCreateInstance(CLASS_IMMDeviceEnumerator, nil, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, deviceEnumerator);
deviceEnumerator.GetDefaultAudioEndpoint(eRender, eConsole, defaultDevice);
defaultDevice.Activate(IID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, nil, endpointVolume);
end;
end.
Windows XP:
function SetMasterVolume(VolToSet: word; out VolSet: word): MMResult;
var
MixerHandle: HMixer;
Volume: TMixerControlDetails_Unsigned;
MixerLine: TMixerLine;
MixerLineControls: TMixerLineControls;
VolumeCtrl: TMixerControl;
MixerControlDetails: TMixerControlDetails;
begin
// Get mixer handle
Result := mixerOpen(@MixerHandle, 0, 0, 0, 0);
if Result <> MMSYSERR_NOERROR then Exit;
try
// Get master volume line
FillChar(MixerLine, SizeOf(TMixerLine), 0);
MixerLine.cbStruct := SizeOf(TMixerLine);
MixerLine.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
Result := mixerGetLineInfo(MixerHandle, @MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
if Result <> MMSYSERR_NOERROR then Exit;
// Get the volume control of the master volume line
FillChar(VolumeCtrl, SizeOf(TMixerControl), 0);
MixerLineControls.cbStruct := SizeOf(TMixerLineControls);
MixerLineControls.dwLineID := MixerLine.dwLineID;
MixerLineControls.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME;
MixerLineControls.cControls := 1;
MixerLineControls.cbmxctrl := SizeOf(TMixerControl);
MixerLineControls.pamxctrl := @VolumeCtrl;
Result := mixerGetLineControls(MixerHandle,@MixerLineControls,MIXER_GETLINECONTROLSF_ONEBYTYPE);
if Result <> MMSYSERR_NOERROR then Exit;
// Set details (volume) for the volume control of the master volume line
FillChar(MixerControlDetails, SizeOf(TMixerControlDetails), 0);
MixerControlDetails.cbStruct := SizeOf(TMixerControlDetails);
MixerControlDetails.dwControlID := VolumeCtrl.dwControlID;
MixerControlDetails.cChannels := 1;
MixerControlDetails.cMultipleItems := 0;
MixerControlDetails.cbDetails := SizeOf(TMixerControlDetails_Unsigned);
MixerControlDetails.paDetails := @Volume;
Volume.dwValue := VolToSet;
Result := mixerSetControlDetails(MixerHandle, @MixerControlDetails,MIXER_SETCONTROLDETAILSF_VALUE);
finally
mixerClose(MixerHandle);
end;
end;
And the call:
var y:word;
begin
SetMasterVolume(2000,y);
end;
Final code is(for Delphi 7):
unit DevUnit;
interface
uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL,ComObj;
const
// TypeLibrary Major and minor versions
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}';
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;
IMMAudioEndpointVolume = 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 fLevel: single):Integer; stdcall;
Function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: single; pguidEventContext: PGUID):Integer; stdcall;
Function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: single; pguidEventContext: PGUID):Integer; stdcall;
Function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: single) : Integer; stdcall;
Function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: single) : 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: single; out pflVolumeMaxdB: single; out pflVolumeIncrementdB: single): Integer; stdcall;
end;
IPropertyStore = interface(IUnknown)
end;
type
IMMDevice = interface(IUnknown)
['{D666063F-1587-4E43-81F1-B948E807363F}']
Function Activate( refId :PGUID;
dwClsCtx: DWORD;
pActivationParams: PInteger ;
out pEndpointVolume: IMMAudioEndpointVolume): 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}']
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.
The MMDevApi has a number of incorrect declarations. The double parameters should be single. The Boolean parameters work better as integer. And many if not all of the TGUID parameters should be PGUID. After correcting the declarations I was able to set the mute and the volume level.
来源:https://stackoverflow.com/questions/3437050/how-to-adjust-master-volume-in-vista-xp