2007. február 28., szerda

How to set the master volume


Problem/Question/Abstract:

How can I set the master volume? I don't want to use an external file like a DLL.

Answer:

Solve 1:

The "Mixer" parameter of SetMasterVolume has to be either a mixer device ID in the range 0..mixerGetNumDevs-1 or a mixer handle returned by a call to mixerOpen().


interface

uses
  SysUtils, Windows, MMSystem;

procedure SetMasterVolume(Mixer: hMixerObj; Value: Word);

implementation

function GetMasterVolumeControl(Mixer: hMixerObj; var Control: TMixerControl): MMResult;
{Returns True on success}
var
  Line: TMixerLine;
  Controls: TMixerLineControls;
begin
  ZeroMemory(@Line, SizeOf(Line));
  Line.cbStruct := SizeOf(Line);
  Line.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
  Result := mixerGetLineInfo(Mixer, @Line, MIXER_GETLINEINFOF_COMPONENTTYPE);
  if Result = MMSYSERR_NOERROR then
  begin
    ZeroMemory(@Controls, SizeOf(Controls));
    Controls.cbStruct := SizeOf(Controls);
    Controls.dwLineID := Line.dwLineID;
    Controls.cControls := 1;
    Controls.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME;
    Controls.cbmxctrl := SizeOf(Control);
    Controls.pamxctrl := @Control;
    Result := mixerGetLineControls(Mixer, @Controls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
  end;
end;

procedure SetMasterVolume(Mixer: hMixerObj; Value: Word);
var
  MasterVolume: TMixerControl;
  Details: TMixerControlDetails;
  UnsignedDetails: TMixerControlDetailsUnsigned;
  Code: MMResult;
begin
  Code := GetMasterVolumeControl(Mixer, MasterVolume);
  if Code = MMSYSERR_NOERROR then
  begin
    with Details do
    begin
      cbStruct := SizeOf(Details);
      dwControlID := MasterVolume.dwControlID;
      cChannels := 1; {set all channels}
      cMultipleItems := 0;
      cbDetails := SizeOf(UnsignedDetails);
      paDetails := @UnsignedDetails;
    end;
    UnsignedDetails.dwValue := Value;
    Code := mixerSetControlDetails(Mixer, @Details, MIXER_SETCONTROLDETAILSF_VALUE);
  end;
  if Code <> MMSYSERR_NOERROR then
    raise Exception.CreateFmt('SetMasterVolume failure, ' + 'multimedia system error #%d', [Code]);
end;


Solve 2:

uses
  MMSystem;

function GetVolumeControl(aMixer: HMixer; componentType, ctrlType: Longint;
  var mxc: TMixerControl): Boolean;
var
  mxl: TMixerLine;
  mxlc: TMixerLineControls;
  rc: Longint;
begin
  Result := FALSE;
  FillChar(mxl, SizeOf(TMixerLine), 0);
  mxl.cbStruct := SizeOf(TMixerLine);
  mxl.dwComponentType := componentType;
  {Obtain a line corresponding to the component type}
  rc := mixerGetLineInfo(aMixer, @mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);
  if rc = MMSYSERR_NOERROR then
  begin
    mxlc.cbStruct := SizeOf(TMixerLineControls);
    mxlc.dwLineID := mxl.dwLineID;
    mxlc.dwControlType := ctrlType;
    mxlc.cControls := 1;
    mxlc.cbmxctrl := SizeOf(TMixerLine);
    mxlc.pamxctrl := @mxc;
    mxlc.pamxctrl^.cbStruct := SizeOf(TMixerControl);
    mixerGetLineControls(aMixer, @mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
    rc := mixerGetLineControls(aMixer, @mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
    Result := rc = MMSYSERR_NOERROR;
  end;
end;

function SetVolumeControl(aMixer: HMixer; mxc: TMixerControl; volume:
  LongInt): Boolean;
var
  mxcd: TMixerControlDetails;
  vol: TMixerControlDetails_Unsigned;
  rc: MMRESULT;
begin
  FillChar(mxcd, SizeOf(mxcd), 0);
  mxcd.dwControlID := mxc.dwControlID;
  mxcd.cbStruct := SizeOf(TMixerControlDetails);
  mxcd.cbDetails := SizeOf(TMixerControlDetails_Unsigned);
  mxcd.paDetails := @vol;
  mxcd.cChannels := 1;
  vol.dwValue := volume;
  rc := mixerSetControlDetails(aMixer, @mxcd, MIXER_SETCONTROLDETAILSF_VALUE);
  Result := rc = MMSYSERR_NOERROR;
end;

function InitMixer: HMixer;
var
  Err: MMRESULT;
begin
  Err := mixerOpen(@Result, 0, 0, 0, 0);
  if Err <> MMSYSERR_NOERROR then
    Result := 0;
end;


Usage example:


procedure SetMasterVolumeToZero;
var
  MyMixerHandle: HMixer;
  MyVolCtrl: TMixerControl;
begin
  MyMixerHandle := InitMixer;
  if MyMixerHandle <> 0 then
  try
    FillChar(MyVolCtrl, SizeOf(MyVolCtrl), 0);
    if GetVolumeControl(MyMixerHandle, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,
      MIXERCONTROL_CONTROLTYPE_VOLUME, MyVolCtrl) then
    begin
      {The last parameter (0) here is the volume level}
      if SetVolumeControl(MyMixer, MyVolCtrl, 0) then
        ShowMessage('Volume should now be set to zero');
    end;
  finally
    mixerClose(MyMixer);
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése