📄 amixer.pas
字号:
FData := AData;
XMixer := AMixer;
FControls := TMixerControls.Create (AMixer, AData);
end;
destructor TMixerConnection.Destroy;
begin
FControls.Free;
inherited;
end;
{-----------------}
{TMixerConnections}
{-----------------}
constructor TMixerConnections.Create (AMixer:TAudioMixer; AData:TMixerLine);
var A,B:Integer;
ML:TMixerLine;
begin
XMixer := AMixer;
FConnections := TPointerList.Create;
FConnections.OnFreeItem := Dofreeitem;
ML.cbStruct := SizeOf(TMixerLine);
ML.dwDestination := AData.dwDestination;
For A := 0 to AData.cConnections-1 do
begin
ML.dwSource := A;
B := MixerGetLineInfo (AMixer.MixerHandle, @ML, MIXER_GETLINEINFOF_SOURCE);
If B = MMSYSERR_NOERROR then
FConnections.Add (Pointer(TMixerConnection.Create (XMixer, ML)));
end;
end;
destructor TMixerConnections.Destroy;
begin
FConnections.Free;
inherited;
end;
procedure TMixerConnections.DoFreeItem (Pntr:Pointer);
begin
TMixerConnection(Pntr).Free;
end;
function TMixerConnections.GetConnection (Ind:Integer):TMixerConnection;
begin
Result := FConnections.Pointer[Ind];
end;
function TMixerConnections.GetCount:Integer;
begin
Result := FConnections.Count;
end;
{-----------------}
{TMixerDestination}
{-----------------}
constructor TMixerDestination.Create (AMixer:TAudioMixer; AData:TMixerLine);
begin
FData := AData;
XMixer := AMixer;
FConnections := TMixerConnections.Create (XMixer, FData);
FControls := TMixerControls.Create (XMixer, AData);
end;
destructor TMixerDestination.Destroy;
begin
Fcontrols.Free;
FConnections.Free;
inherited;
end;
{------------------}
{TMixerDestinations}
{------------------}
constructor TMixerDestinations.Create (AMixer:TAudioMixer);
var A,B:Integer;
ML:TMixerLine;
begin
FDestinations := TPointerList.Create;
FDestinations.OnFreeItem := DoFreeItem;
For A := 0 to AMixer.MixerCaps.cDestinations-1 do
begin
ML.cbStruct := SizeOf(TMixerLine);
ML.dwDestination := A;
B := MixerGetLineInfo (AMixer.MixerHandle, @ML, MIXER_GETLINEINFOF_DESTINATION);
If B = MMSYSERR_NOERROR then
FDestinations.Add (Pointer(TMixerDestination.Create (AMixer, ML)));
end;
end;
procedure TMixerDestinations.DoFreeItem (Pntr:Pointer);
begin
TMixerDestination(Pntr).Free;
end;
destructor TMixerDestinations.Destroy;
begin
FDestinations.Free;
inherited;
end;
function TMixerDestinations.GetDestination (Ind:Integer):TMixerDestination;
begin
Result := FDestinations.Pointer[Ind];
end;
function TMixerDestinations.GetCount:Integer;
begin
Result := FDestinations.Count;
end;
{-----------}
{TAudioMixer}
{-----------}
constructor TAudioMixer.Create (AOwner:TComponent);
begin
inherited Create (AOwner);
FDestinations := nil;
XWndHandle := AllocateHWnd (MixerCallBack);
FMixersCount := mixerGetNumDevs;
FMixerId := -1;
SetMixerId (0);
end;
destructor TAudioMixer.Destroy;
begin
CloseMixer;
if XWndHandle <> 0 then
DeAllocateHwnd (XWndHandle);
inherited;
end;
procedure TAudioMixer.CloseMixer;
begin
If FMixerId >= 0 then
begin
mixerClose (FMixerHandle);
FMixerId := -1;
end;
FDestinations.Free;
FDestinations := nil;
end;
procedure TAudioMixer.SetMixerId (Value:Integer);
begin
If FMixersCount = 0 then
Exit;
If Value >= FMixersCount then
Value := FMixersCount - 1;
CloseMixer;
If Value >= 0 then
begin
If mixerOpen (@FMixerHandle, Value, XWndHandle, 0, CALLBACK_WINDOW OR MIXER_OBJECTF_MIXER) = MMSYSERR_NOERROR then
begin
FMixerId := Value;
mixerGetDevCaps (MixerId, @FMixerCaps, SizeOf (TMixerCaps));
if FMixerCaps.wMid = MM_MICROSOFT then
FManufacturer := 'Microsoft'
else
FManufacturer := IntToStr(FMixerCaps.wMid) + ' = Unknown';
FDriverVersion := FMixerCaps.vDriverVersion;
FProductId := FMixerCaps.wPid;
FProductName := StrPas(FMixerCaps.szPName);
FNumberOfLine := FMixerCaps.cDestinations;
FDestinations := TMixerDestinations.Create (Self);
end;
end;
end;
procedure TAudioMixer.MixerCallBack (var Msg:TMessage);
begin
case Msg.Msg of
MM_MIXM_LINE_CHANGE:
If Assigned (OnLineChange) then
OnLineChange (Self, Msg.wParam, Msg.lParam);
MM_MIXM_CONTROL_CHANGE:
If Assigned (OnControlChange) then
OnControlChange (Self, Msg.wParam, Msg.lParam);
else
Msg.Result := DefWindowProc (XWndHandle, Msg.Msg, Msg.WParam, Msg.LParam);
end;
end;
function TAudioMixer.GetVolume (ADestination,AConnection:Integer;var LeftVol, RightVol, Mute:Integer;var Stereo, VolDisabled, MuteDisabled:Boolean):Boolean;
var MD:TMixerDestination;
MC:TMixerConnection;
Cntrls:TMixerControls;
MCD:TMixerControlDetails;
Cntrl:PMixerControl;
A,B:Integer;
ML:TMixerLine;
details:array [0..30] of Integer;
begin
Result := False;
Stereo := False;
MD := Destinations[ADestination];
If MD <> nil then
begin
If AConnection = -1 then
begin
Cntrls := MD.Controls;
ML := MD.Data;
end
else
begin
MC := MD.Connections[AConnection];
If MC <> nil then
begin
Cntrls := MC.Controls;
ML := MC.Data;
end
else
Cntrls := nil;
end;
If Cntrls <> nil then
begin
A := 0;
Result := True;
LeftVol := -1;
RightVol := -1;
Mute := -1;
while ((LeftVol = -1) OR (Mute = -1)) AND (A < Cntrls.Count) do
begin
Cntrl := Cntrls[A];
If Cntrl <> nil then
begin
If ((Cntrl.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME) OR
(Cntrl.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE)) AND
(Cntrl.fdwControl AND MIXERCONTROL_CONTROLF_MULTIPLE <> MIXERCONTROL_CONTROLF_MULTIPLE)
then
begin
if (Cntrl.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE) then
MCD.cbStruct := SizeOf(TMixerControlDetails) //1
else
MCD.cbStruct := SizeOf(TMixerControlDetails);
MCD.dwControlID := Cntrl.dwControlID;
If Cntrl.fdwControl AND MIXERCONTROL_CONTROLF_UNIFORM > 0 then
MCD.cChannels := 1
else
MCD.cChannels := ML.cChannels;
MCD.cMultipleItems := 0;
MCD.cbDetails := SizeOf(Integer);
MCD.paDetails := @details;
B := mixerGetControlDetails (FMixerHandle, @MCD, MIXER_GETCONTROLDETAILSF_VALUE);
If B = MMSYSERR_NOERROR then
begin
If (Cntrl.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME) AND (LeftVol = -1) then
begin
VolDisabled := Cntrl.fdwControl AND MIXERCONTROL_CONTROLF_DISABLED > 0;
If not VolDisabled then
begin
LeftVol := details[0];
If MCD.cChannels > 1 then
begin
RightVol := Details[1];
Stereo := True;
end;
end;
end
else
If (Cntrl.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE) AND (Mute = -1) then
begin
MuteDisabled := Cntrl.fdwControl AND MIXERCONTROL_CONTROLF_DISABLED > 0;//2
If not MuteDisabled then
begin
If Details[0] <> 0 then
Mute := 1
else
Mute := 0;
end;
end;
end;
end;
end;
Inc (A);
end;
If Mute = -1 then
begin
If AConnection <> -1 then
begin
Cntrls := MD.Controls;
ML := MD.Data;
If Cntrls <> nil then
begin
A := 0;
while (Mute = -1) AND (A < Cntrls.Count) do
begin
Cntrl := Cntrls[A];
If (Cntrl.dwControlType AND MIXERCONTROL_CONTROLTYPE_MIXER = MIXERCONTROL_CONTROLTYPE_MIXER) OR
(Cntrl.dwControlType AND MIXERCONTROL_CONTROLTYPE_MUX = MIXERCONTROL_CONTROLTYPE_MUX) then
// Mux is similar to mixer, but only one line can be selected at a time
begin
MCD.cbStruct := SizeOf(TMixerControlDetails);
MCD.dwControlID := Cntrl.dwControlID;
If Cntrl.fdwControl AND MIXERCONTROL_CONTROLF_UNIFORM > 0 then
MCD.cChannels := 1
else
MCD.cChannels := ML.cChannels;
If Cntrl.fdwControl AND MIXERCONTROL_CONTROLF_MULTIPLE = MIXERCONTROL_CONTROLF_MULTIPLE then
MCD.cMultipleItems := Cntrl.cMultipleItems
else
MCD.cMultipleItems := 0;
MCD.cbDetails := 4;
MCD.paDetails := @Details;
B := mixerGetControlDetails (FMixerHandle,@MCD,MIXER_GETCONTROLDETAILSF_VALUE);
If B = MMSYSERR_NOERROR then
Mute := Details[AConnection];
end;
Inc (A);
end;
end;
end;
end;
If LeftVol = -1 then
VoldIsabled := True;
If Mute = -1 then
MuteDisabled := True;
end;
end;
end;
function TAudioMixer.SetVolume (ADestination, AConnection:Integer; LeftVol, RightVol, Mute:Integer):Boolean;
var MD:TMixerDestination;
MC:TMixerConnection;
Cntrls:TMixerControls;
MCD:TMixerControlDetails;
Cntrl:PMixerControl;
A,B:Integer;
ML:TMixerLine;
details:array [0..30] of Integer;
VolSet,MuteSet:Boolean;
begin
Result := False;
MD := Destinations[ADestination];
If MD <> nil then
begin
If AConnection = -1 then
begin
Cntrls := MD.Controls;
ML := MD.Data;
end
else
begin
MC := MD.Connections[AConnection];
If MC <> nil then
begin
Cntrls := MC.Controls;
ML := MC.Data;
end
else
Cntrls := nil;
end;
If Cntrls <> nil then
begin
A := 0;
VolSet := LeftVol = -1;
MuteSet := Mute = -1;
Result := True;
while (not VolSet OR not MuteSet) AND (A < Cntrls.Count) do
begin
Cntrl := Cntrls[A];
If Cntrl <> nil then
begin
If ((Cntrl.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME) OR
(Cntrl.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE)) AND
(Cntrl.fdwControl AND MIXERCONTROL_CONTROLF_MULTIPLE <> MIXERCONTROL_CONTROLF_MULTIPLE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -