unit Mixer;
interface { ----------------------------------------------------------------- }
uses Windows,Classes,SysUtils,MPlayer,MMSystem,Math;
// BasicFunctions found at [url]http://delphi.about.com[/url]
//
// MixerParameters
//
// VolumePos = Range from 100 to 65535
// --------------------------------------------------------------------
// set TrackBar : Min=100, Max=65535, LineSize=655, PageSize=6553, Frequency=6553
// SelStart=0, SelEnd=0, Height=20, ThumbLength=10,
// TickStyle=tsAuto
//
//
// FadePos = Range from -12 to +12
// --------------------------------------------------------------------
// set TrackBar : Min=-12, Max=12, LineSize=2, PageSize=4, Frequency=4
// SelStart=0, SelEnd=-1, Height=20, ThumbLength=10,
// TickStyle=tsAuto
//
// MediaPlayerParameters
// VolumePos = Range from 0 to 1000
type tMixerCtrl = (MasterOut,WaveOut,CDOut,LineOut);
var AvailMixer : TStringList;
procedure GetAvailMixer;
procedure GetMixerIDs;
procedure SetActiveMixer(NewMixerID:Integer);
function GetVolume(Ctrl:TMixerCtrl):Integer;
procedure SetVolume(Ctrl:tMixerCtrl;Volume:Integer);
function GetBalance(Ctrl:TMixerCtrl):Integer;
procedure SetBalance(Ctrl:tMixerCtrl;Balance:Integer);
function MuteActive(Ctrl:TMixerCtrl):Boolean;
procedure SetMute(Ctrl:tMixerCtrl;State:Boolean);
function GetMediaPlayerVolume(MP:TMediaPlayer):Integer;
procedure SetMediaPlayerVolume(MP:TMediaPlayer;Volume:Integer);
implementation { ----------------------------------------------------------- }
{
Achtung : Die Balance ist offenbar nicht direkt zu lesen/setzen.
Daher erfolgt die Berechnung über Differenz VolumenLinks und
VolumenRechts. Das funktioniert nur, wenn minVolumen=257(?).
Außerdem führt die VolumenÄnderung im Mixer auf Null zum Zurück-
setzen der Balance auf Null?!
>> Lösung trotz intensivem Basteln nicht gefunden!
>> Vermutlich ist hier noch ein Logikfehler!! }
// ------------------------------------------------------- MixerDevicesControls
var MixerID : Integer;
OutVolID,
OutMuteID :
Array[MasterOut..LineOut]
of DWord;
procedure GetMixerIDs;
var CtrlType : DWord;
function GetID(CompType:DWORD;ControlType:DWord):DWORD;
var mxl : MIXERLINE;
mxc : MIXERCONTROL;
mxlc : MIXERLINECONTROLS;
begin
Result :=0;
mxl.cbStruct :=SizeOf(mxl);
mxl.dwComponentType:=CompType;
if (mixerGetLineInfo(MixerID,@mxl,MIXER_GETLINEINFOF_COMPONENTTYPE)=MMSYSERR_NOERROR)
then begin
mxlc.cbStruct :=SizeOf(mxlc);
mxlc.dwLineID :=mxl.dwLineID;
mxlc.dwControlType:=ControlType;
mxlc.cControls :=mxl.cControls;
mxlc.cbmxctrl :=sizeof(mxc);
mxlc.pamxctrl :=@mxc;
if (mixerGetLineControls(MixerID,@mxlc,MIXER_GETLINECONTROLSF_ONEBYTYPE)=MMSYSERR_NOERROR)
then
Result:=mxc.dwControlID;
end;
end;
begin
CtrlType:=MixerControl_ControlType_Volume;
OutVolID[MasterOut] :=GetID(MixerLine_ComponentType_DST_Speakers, CtrlType);
OutVolID[WaveOut] :=GetID(MixerLine_ComponentType_SRC_WaveOut, CtrlType);
OutVolID[CDOut] :=GetID(MixerLine_ComponentType_SRC_CompactDisc,CtrlType);
OutVolID[LineOut] :=GetID(MixerLine_ComponentType_SRC_Line, CtrlType);
CtrlType:=MixerControl_ControlType_Mute;
OutMuteID[MasterOut]:=GetID(MixerLine_ComponentType_DST_Speakers, CtrlType);
OutMuteID[WaveOut] :=GetID(MixerLine_ComponentType_SRC_WaveOut, CtrlType);
OutMuteID[CDOut] :=GetID(MixerLine_ComponentType_SRC_CompactDisc,CtrlType);
OutMuteID[LineOut] :=GetID(MixerLine_ComponentType_SRC_Line, CtrlType);
end;
function pGetVolumeLR(ID:DWord;
var VolumeLeft,VolumeRight:DWord):Boolean;
var Volume :
Array[0..1]
Of TMixerControlDetails_Unsigned;
mxcd : TMixerControlDetails;
begin
with mxcd
do begin
cbStruct :=SizeOf(mxcd);
dwControlID :=ID;
cChannels :=2;
cMultipleItems:=0;
cbDetails :=SizeOf(TMixerControlDetails_Unsigned)*2;
paDetails :=@Volume;
Result:=(mixerGetControlDetails(MixerID,@mxcd,MIXER_GETCONTROLDETAILSF_VALUE)=MMSYSERR_NOERROR);
end;
VolumeLeft :=Volume[0].dwValue;
// reversal to SetVolume
VolumeRight:=Volume[1].dwValue;
// why ??
end;
function pSetVolumeLR(ID,VolumeLeft,VolumeRight:DWord):Boolean;
var Volume :
Array[0..1]
Of TMixerControlDetails_Unsigned;
mxcd : TMixerControlDetails;
begin
if (VolumeLeft <257)
and (VolumeRight=0)
then VolumeLeft :=257;
if (VolumeRight<257)
and (VolumeLeft =0)
then VolumeRight:=257;
Volume[0].dwValue:=VolumeRight;
Volume[1].dwValue:=VolumeLeft;
with mxcd
do begin
cbStruct :=SizeOf(mxcd);
dwControlID :=ID;
cChannels :=2;
cMultipleItems:=0;
cbDetails :=SizeOf(TMixerControlDetails_Unsigned)*2;
paDetails :=@Volume;
Result:=(mixerSetControlDetails(MixerID,@mxcd,MIXER_SETCONTROLDETAILSF_VALUE)=MMSYSERR_NOERROR);
end;
end;
function pGetMute(ID:DWord;
var EnableMute:Boolean):Boolean;
var mxcd : TMixerControlDetails;
mxcdb : TMixerControlDetailsBoolean;
begin
with mxcd
do begin
cbStruct :=SizeOf(mxcd);
dwControlID :=ID;
cChannels :=1;
cMultipleItems:=0;
cbDetails :=SizeOf(TMixerControlDetailsBoolean);
paDetails :=@mxcdb;
Result:=(mixerGetControlDetails(MixerID,@mxcd,MIXER_GETCONTROLDETAILSF_VALUE)=MMSYSERR_NOERROR);
end;
EnableMute:=LongBool(mxcdb.fValue);
end;
function pSetMute(ID:DWord;EnableMute:Boolean):Boolean;
var mxcd : TMixerControlDetails;
mxcdb : TMixerControlDetailsBoolean;
begin
with mxcd
do begin
cbStruct :=SizeOf(mxcd);
dwControlID :=ID;
cChannels :=1;
cMultipleItems:=0;
cbDetails :=SizeOf(TMixerControlDetailsBoolean);
paDetails :=@mxcdb;
LongBool(mxcdb.fValue):=EnableMute;
Result:=(mixerSetControlDetails(MixerID,@mxcd,MIXER_SETCONTROLDETAILSF_VALUE)=MMSYSERR_NOERROR);
end;
end;
// --------------------------------------------------------- user interface NEW
procedure GetAvailMixer;
var DNum,i : Integer;
Caps : TWaveOutCapsA;
begin
AvailMixer.Clear;
DNum:=waveOutGetNumDevs;
// number of devices
for i:=0
to DNum-1
do begin // query devicenames
waveOutGetDevCaps(i,@Caps,SizeOf(TWaveOutCapsA));
AvailMixer.Add(
String(Caps.szPname));
end;
end;
procedure SetActiveMixer(NewMixerID:Integer);
begin
if MixerID<AvailMixer.Count
then begin
MixerID:=NewMixerID;
GetMixerIDs;
end;
end;
function GetVolume(Ctrl:TMixerCtrl):Integer;
var volL,volR : DWord;
begin
pGetVolumeLR(OutVolID[Ctrl],volL,volR);
Result:=Max(volL,volR);
if Result<257
then Result:=257;
end;
procedure SetVolume(Ctrl:tMixerCtrl;Volume:Integer);
var F,volL,volR : Integer;
vL,vR : DWord;
begin
if Volume<257
then Volume:=257;
pGetVolumeLR(OutVolID[Ctrl],vL,vR);
volL:=vL;
volR:=vR;
if volL=volR
then F:=0
else if volL<volR
then F:= 12-((volL*12)
div volR)
else F:=-(12-((volR*12)
div volL));
volL:=Volume;
if F<0
then dec(volL,(volL
div 12)*abs(F));
volR:=Volume;
if F>0
then dec(volR,(volR
div 12)*F);
pSetVolumeLR(OutVolID[Ctrl],volL,volR);
end;
function GetBalance(Ctrl:TMixerCtrl):Integer;
var volL,volR : DWord;
F : Integer;
begin
pGetVolumeLR(OutVolID[Ctrl],volL,volR);
if volL=volR
then F:=0
else if volL<volR
then F:= 12-((volL*12)
div volR)
else F:=-(12-((volR*12)
div volL));
Result:=F;
end;
procedure SetBalance(Ctrl:tMixerCtrl;Balance:Integer);
var F,volL,volR : Integer;
vL,vR : DWord;
begin
pGetVolumeLR(OutVolID[Ctrl],vL,vR);
volL:=Max(vL,vR);
volR:=volL;
F :=abs(Balance);
if Balance<0
then dec(volL,(volL
div 12)*F);
if Balance>0
then dec(volR,(volR
div 12)*F);
pSetVolumeLR(OutVolID[Ctrl],volL,volR);
end;
function MuteActive(Ctrl:TMixerCtrl):Boolean;
begin
pGetMute(OutMuteID[Ctrl],Result);
end;
procedure SetMute(Ctrl:tMixerCtrl;State:Boolean);
begin
pSetMute(OutMuteID[Ctrl],State);
end;
// ------------------------------------------ user interface MediaPlayer volume
const MCI_SETAUDIO = $0873;
MCI_DGV_SETAUDIO_VOLUME = $4002;
MCI_DGV_SETAUDIO_ITEM = $00800000;
MCI_DGV_SETAUDIO_VALUE = $01000000;
MCI_DGV_STATUS_VOLUME = $4019;
type MCI_DGV_SETAUDIO_PARMS =
record
dwCallback : DWORD;
dwItem : DWORD;
dwValue : DWORD;
dwOver : DWORD;
lpstrAlgorithm : PChar;
lpstrQuality : PChar;
end;
MCI_STATUS_PARMS =
record
dwCallback : DWORD;
dwReturn : DWORD;
dwItem : DWORD;
dwTrack : DWORD;
end;
procedure SetMediaPlayerVolume(MP:TMediaPlayer;Volume:Integer);
var p : MCI_DGV_SETAUDIO_PARMS;
begin
p.dwCallback :=0;
p.dwItem :=MCI_DGV_SETAUDIO_VOLUME;
p.dwValue :=Volume;
p.dwOver :=0;
p.lpstrAlgorithm:=nil;
p.lpstrQuality :=nil;
mciSendCommand(MP.DeviceID,MCI_SETAUDIO,
MCI_DGV_SETAUDIO_VALUE
or MCI_DGV_SETAUDIO_ITEM, Cardinal(@p));
end;
function GetMediaPlayerVolume(MP:TMediaPlayer):Integer;
var p : MCI_STATUS_PARMS;
begin
p.dwCallback:=0;
p.dwItem :=MCI_DGV_STATUS_VOLUME;
mciSendCommand(MP.DeviceID,MCI_STATUS,MCI_STATUS_ITEM,Cardinal(@p));
Result:=p.dwReturn;
end;
initialization { ------------------------------------------------------------ }
AvailMixer :=TStringList.Create;
// init list of mixer names
AvailMixer.Sorted:=false;
// don't sort mixer list
GetAvailMixer;
// get available mixer and save to list
MixerID :=0;
// use current mixer at start
GetMixerIDs;
finalization { -------------------------------------------------------------- }
AvailMixer.Free;
end.