📄 mmmixer.pas
字号:
TMMItemInfo = record
Val1, Val2: TMMItemParam;
Name : string;
end;
{-- TMMCustomMixerControl -------------------------------------------}
TMMCustomMixerControl = class(TMMNonVisualComponent)
private
FAudioLine : TMMAudioLine;
FControlId : TMMControlId;
FControlType : TMMControlType;
FControlClass : TMMControlClass;
FControlSetup : TMMControlSetup;
FObserver : TMMObserver;
FObservable : TMMObservable;
FControlInfo : TMMControlInfo;
FOnChange : TNotifyEvent;
FCDummy : TMMControlClass;
procedure SetAudioLine(Value: TMMAudioLine);
procedure SetControlId(Value: TMMControlId);
procedure SetControlType(Value: TMMControlType);
procedure LineNotify(Sender, Data: TObject);
function GetMixer: TMMMixerDevice;
function GetLineId: TMMLineId;
function StoreControlId: Boolean;
procedure SetControlInfo(const Value: TMMControlInfo);
function ValueIndex(C: TMMChannel; Item: TMMItemIndex): Integer;
function GetItemInfo(Index: TMMItemIndex): TMMItemInfo;
function StoreControlType: Boolean;
protected
procedure UpdateControl; virtual;
procedure Loaded; override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure NeedMixer;
procedure NeedId;
procedure Changed; virtual;
procedure DoChange; dynamic;
procedure ControlIdChanged; virtual;
function GetBoolean: Boolean; virtual;
procedure SetBoolean(Value: Boolean); virtual;
function GetUnsigned: Cardinal; virtual;
procedure SetUnsigned(Value: Cardinal); virtual;
function GetSigned: Integer; virtual;
procedure SetSigned(Value: Integer); virtual;
function GetAvailable: Boolean; virtual;
procedure CalcParams(C: TMMChannel; Item: TMMItemIndex; var Ch: TMMChannelIndex; var It: TMMItemIndex);
function ValidControl(const Info: TMixerControl): Boolean; virtual;
function GetControlSetup: TMMControlSetup;
function GetChannels: TMMChannelIndex; virtual;
function GetItems: TMMItemIndex; virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure AddObserver(O: TMMObserver);
procedure RemoveObserver(O: TMMObserver);
function GetChannelSigned(C: TMMChannel; Item: TMMItemIndex): Integer; virtual;
procedure SetChannelSigned(C: TMMChannel; Item: TMMItemIndex; Value: Integer); virtual;
function GetChannelUnsigned(C: TMMChannel; Item: TMMItemIndex): Cardinal; virtual;
procedure SetChannelUnsigned(C: TMMChannel; Item: TMMItemIndex; Value: Cardinal); virtual;
function GetChannelBoolean(C: TMMChannel; Item: TMMItemIndex): Boolean; virtual;
procedure SetChannelBoolean(C: TMMChannel; Item: TMMItemIndex; Value: Boolean); virtual;
function ValidMixer: Boolean;
function CanModify: Boolean;
function GetItemForLine(Line: TMMAudioLine): TMMItemIndex;
property Mixer: TMMMixerDevice read GetMixer;
property LineId: TMMLineId read GetLineId;
property AsBoolean: Boolean read GetBoolean write SetBoolean;
property AsUnsigned: Cardinal read GetUnsigned write SetUnsigned;
property AsSigned: Integer read GetSigned write SetSigned;
property Available: Boolean read GetAvailable;
property Channels: TMMChannelIndex read GetChannels;
property Items: TMMItemIndex read GetItems;
property ItemInfo[Index:TMMItemIndex]: TMMItemInfo read GetItemInfo;
published
property AudioLine: TMMAudioLine read FAudioLine write SetAudioLine;
property ControlId: TMMControlId read FControlId write SetControlId stored StoreControlId;
property ControlClass: TMMControlClass read FControlClass write FCDummy stored False;
property ControlInfo: TMMControlInfo read FControlInfo write SetControlInfo stored False;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
protected
property ControlType: TMMControlType read FControlType write SetControlType stored StoreControlType;
end;
TMMControlIdChange = class(TMMMixerChange)
end;
EMMMixerControlError = class(Exception)
end;
{-- TMMMixerControl -----------------------------------------------------}
TMMMixerControl = class(TMMCustomMixerControl)
published
property ControlType;
end;
const
MaxLeftPan = -32768;
MaxRightPan = 32767;
type
{-- TMMVolumeControl ----------------------------------------------------}
TMMVolumeControl = class(TMMCustomMixerControl)
private
FPanValue: Integer;
procedure SetPanValue(Value: Integer);
protected
function ValidControl(const Info: TMixerControl): Boolean; override;
procedure SetUnsigned(Value: Cardinal); override;
procedure SetSigned(Value: Integer); override;
function Pan(C: TMMChannel): Extended;
public
constructor Create(AOwner: TComponent); override;
procedure SetChannelSigned(C: TMMChannel; Item: TMMItemIndex; Value: Integer); override;
procedure SetChannelUnsigned(C: TMMChannel; Item: TMMItemIndex; Value: Cardinal); override;
published
property PanValue: Integer read FPanValue write SetPanValue default 0;
end;
{-- TMMPanControl -------------------------------------------------------}
TMMPanControl = class(TMMCustomMixerControl)
private
FVolume : TMMVolumeControl;
FObserver : TMMObserver;
FSimulate : Boolean;
FSimActive : Boolean;
FValue : Integer;
procedure SetControl(Value:TMMVolumeControl);
procedure SetSimulate(Value:Boolean);
procedure VolumeNotify(Sender,Data:TObject);
protected
function ValidControl(const Info: TMixerControl): Boolean; override;
procedure UpdatePan;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure UpdatePanValue;
procedure UpdateVolumePan;
procedure SetSigned(Value: Integer); override;
function GetSigned: Integer; override;
function GetAvailable: Boolean; override;
procedure UpdateControl; override;
function GetChannels: TMMChannelIndex; override;
function GetItems: TMMItemIndex; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetChannelSigned(C: TMMChannel; Item: TMMItemIndex): Integer; override;
procedure SetChannelSigned(C: TMMChannel; Item: TMMItemIndex; Value: Integer); override;
published
property VolumeControl: TMMVolumeControl read FVolume write SetControl;
property Simulate: Boolean read FSimulate write SetSimulate default True;
end;
{-- Mixer service -------------------------------------------------------}
{ D3: This lines rely on current Win32 API}
function APIToCompType(dwType: DWORD): TMMComponentType;
function CompTypeToAPI(CompType: TMMComponentType): DWORD;
function DeviceTypeToTarget(DevType: TMMAudioDeviceType): UINT;
function ControlTypeToAPI(ControlType: TMMControlType): DWORD;
function APIToControlType(ControlType: DWORD): TMMControlType;
function APIToControlFlags(fdwControl: DWORD): TMMControlFlags;
function APIToLineFlags(fdwLine: DWORD): TMMLineFlags;
function ControlClassOfType(CT: DWORD): TMMControlClass;
function IsControlTypeSingleSelect(CT: DWORD): Boolean;
function ControlIdToIdent(Id: LongInt; var S: string): Boolean;
function LineIdToIdent(Id: LongInt; var S: string): Boolean;
function ItemIndexToIdent(Id: LongInt; var S: string): Boolean;
function IdentToControlId(const S: string; var Id: LongInt): Boolean;
function IdentToLineId(const S: string; var Id: LongInt): Boolean;
function IdentToItemIndex(const S: string; var Id: LongInt): Boolean;
type
EMMMixerServiceError = class(Exception)
end;
{========================================================================}
implementation
{========================================================================}
uses
MMDesign;
{== Mixer service =======================================================}
const
CompTypes: array[TMMComponentType] of DWORD =
(MIXERLINE_COMPONENTTYPE_DST_DIGITAL,
MIXERLINE_COMPONENTTYPE_DST_HEADPHONES,
MIXERLINE_COMPONENTTYPE_DST_LINE,
MIXERLINE_COMPONENTTYPE_DST_MONITOR,
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,
MIXERLINE_COMPONENTTYPE_DST_TELEPHONE,
MIXERLINE_COMPONENTTYPE_DST_UNDEFINED,
MIXERLINE_COMPONENTTYPE_DST_VOICEIN,
MIXERLINE_COMPONENTTYPE_DST_WAVEIN,
MIXERLINE_COMPONENTTYPE_SRC_ANALOG,
MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY,
MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC,
MIXERLINE_COMPONENTTYPE_SRC_DIGITAL,
MIXERLINE_COMPONENTTYPE_SRC_LINE,
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE,
MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER,
MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER,
MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE,
MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED,
MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT);
{------------------------------------------------------------------------}
function APIToCompType(dwType: DWORD): TMMComponentType;
var
i: TMMComponentType;
begin
for i := Low(TMMComponentType) to High(TMMComponentType) do
if CompTypes[i] = dwType then
begin
Result := i;
Exit;
end;
{ TODO: Should be resource id }
raise EMMMixerServiceError.Create('Undefined API component type');
end;
{------------------------------------------------------------------------}
function CompTypeToAPI(CompType: TMMComponentType): DWORD;
begin
Result := CompTypes[CompType];
end;
{------------------------------------------------------------------------}
function MakeVersion(Maj, Min: Byte): WORD;
begin
Result := MakeWord(Min, Maj);
end;
{------------------------------------------------------------------------}
const
Targets: array[TMMAudioDeviceType] of UINT =
(MIXERLINE_TARGETTYPE_MIDIIN,
MIXERLINE_TARGETTYPE_MIDIOUT,
MIXERLINE_TARGETTYPE_WAVEIN,
MIXERLINE_TARGETTYPE_WAVEOUT,
MIXERLINE_TARGETTYPE_AUX,
MIXERLINE_TARGETTYPE_UNDEFINED);
{------------------------------------------------------------------------}
function DeviceTypeToTarget(DevType: TMMAudioDeviceType): UINT;
begin
Result := Targets[DevType];
end;
{------------------------------------------------------------------------}
const
Types: array[TMMControlType] of DWORD =
(MIXERCONTROL_CONTROLTYPE_CUSTOM,
MIXERCONTROL_CONTROLTYPE_BASS,
MIXERCONTROL_CONTROLTYPE_EQUALIZER,
MIXERCONTROL_CONTROLTYPE_FADER,
MIXERCONTROL_CONTROLTYPE_TREBLE,
MIXERCONTROL_CONTROLTYPE_VOLUME,
MIXERCONTROL_CONTROLTYPE_MIXER,
MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT,
MIXERCONTROL_CONTROLTYPE_MUX,
MIXERCONTROL_CONTROLTYPE_SINGLESELECT,
MIXERCONTROL_CONTROLTYPE_BOOLEANMETER,
MIXERCONTROL_CONTROLTYPE_PEAKMETER,
MIXERCONTROL_CONTROLTYPE_SIGNEDMETER,
MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER,
MIXERCONTROL_CONTROLTYPE_DECIBELS,
MIXERCONTROL_CONTROLTYPE_PERCENT,
MIXERCONTROL_CONTROLTYPE_SIGNED,
MIXERCONTROL_CONTROLTYPE_UNSIGNED,
MIXERCONTROL_CONTROLTYPE_PAN,
MIXERCONTROL_CONTROLTYPE_QSOUNDPAN,
MIXERCONTROL_CONTROLTYPE_SLIDER,
MIXERCONTROL_CONTROLTYPE_BOOLEAN,
MIXERCONTROL_CONTROLTYPE_BUTTON,
MIXERCONTROL_CONTROLTYPE_LOUDNESS,
MIXERCONTROL_CONTROLTYPE_MONO,
MIXERCONTROL_CONTROLTYPE_MUTE,
MIXERCONTROL_CONTROLTYPE_ONOFF,
MIXERCONTROL_CONTROLTYPE_STEREOENH,
MIXERCONTROL_CONTROLTYPE_MICROTIME,
MIXERCONTROL_CONTROLTYPE_MILLITIME);
{------------------------------------------------------------------------}
function ControlTypeToAPI(ControlType: TMMControlType): DWORD;
begin
Result := Types[ControlType];
end;
{------------------------------------------------------------------------}
function APIToControlType(ControlType: DWORD): TMMControlType;
begin
for Result := Low(TMMControlType) to High(TMMControlType) do
if Types[Result] = ControlType then
Exit;
Result := ctCustom; { Because on my computer there are some undefined device }
end;
{------------------------------------------------------------------------}
const
Flags: array[TMMControlFlag] of DWORD =
(MIXERCONTROL_CONTROLF_DISABLED,
MIXERCONTROL_CONTROLF_MULTIPLE,
MIXERCONTROL_CONTROLF_UNIFORM);
{------------------------------------------------------------------------}
function APIToControlFlags(fdwControl: DWORD): TMMControlFlags;
var
i: TMMControlFlag;
begin
Result:= [];
for i:= Low(TMMControlFlag) to High(TMMControlFlag) do
if (fdwControl and Flags[i]) <> 0 then
Include(Result,i);
end;
{------------------------------------------------------------------------}
const
LineFlags: array[TMMLineFlag] of DWORD =
(MIXERLINE_LINEF_ACTIVE,
MIXERLINE_LINEF_DISCONNECTED,
MIXERLINE_LINEF_SOURCE);
{------------------------------------------------------------------------}
function APIToLineFlags(fdwLine: DWORD): TMMLineFlags;
var
i: TMMLineFlag;
begin
Result:= [];
for i:= Low(TMMLineFlag) to High(TMMLineFlag) do
if (fdwLine and LineFlags[i]) <> 0 then
Include(Result,i);
end;
{------------------------------------------------------------------------}
const
CClasses: array[TMMControlClass] of DWORD =
(MIXERCONTROL_CT_CLASS_CUSTOM,
MIXERCONTROL_CT_CLASS_FADER,
MIXERCONTROL_CT_CLASS_LIST,
MIXERCONTROL_CT_CLASS_METER,
MIXERCONTROL_CT_CLASS_NUMBER,
MIXERCONTROL_CT_CLASS_SLIDER,
MIXERCONTROL_CT_CLASS_SWITCH,
MIXERCONTROL_CT_CLASS_TIME);
{------------------------------------------------------------------------}
function ControlClassOfType(CT: DWORD): TMMControlClass;
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -