MMMixer.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:89k
- {========================================================================}
- {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
- {========================================================================}
- {= All Rights Reserved =}
- {========================================================================}
- {= D 01099 Dresden = Tel.: +0351-8012255 =}
- {= Loewenstr.7a = info@swiftsoft.de =}
- {========================================================================}
- {= Actual versions on http://www.swiftsoft.de/mmtools.html =}
- {========================================================================}
- {= This code is for reference purposes only and may not be copied or =}
- {= distributed in any format electronic or otherwise except one copy =}
- {= for backup purposes. =}
- {= =}
- {= No Delphi Component Kit or Component individually or in a collection=}
- {= subclassed or otherwise from the code in this unit, or associated =}
- {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
- {= without express permission from SwiftSoft. =}
- {= =}
- {= For more licence informations please refer to the associated =}
- {= HelpFile. =}
- {========================================================================}
- {= $Date: 12.02.98 - 06:07:59 $ =}
- {========================================================================}
- unit MMMixer;
- {$I COMPILER.INC}
- interface
- uses
- {$IFDEF WIN32}
- Windows,
- {$ELSE}
- WinTypes,
- WinProcs,
- {$ENDIF}
- Messages,
- Classes,
- SysUtils,
- Forms,
- MMSystem,
- MMObj,
- MMUtils,
- MMObsrv,
- MMDevice;
- type
- { D3: This lines rely on current Win32 API}
- { To override Borland's bug directly declare TMixerControl }
- { instead of TMixerControlA }
- PMixerControl = ^TMixerControl;
- TMixerControl = record
- cbStruct : DWORD; { size in bytes of MIXERCONTROL }
- dwControlID : DWORD; { unique control id for mixer device }
- dwControlType: DWORD; { MIXERCONTROL_CONTROLTYPE_xxx }
- fdwControl : DWORD; { MIXERCONTROL_CONTROLF_xxx }
- cMultipleItems: DWORD; { if MIXERCONTROL_CONTROLF_MULTIPLE set }
- szShortName : array[0..MIXER_SHORT_NAME_CHARS - 1] of AnsiChar;
- szName : array[0..MIXER_LONG_NAME_CHARS - 1] of AnsiChar;
- Bounds: record
- case Integer of
- 0: (lMinimum, lMaximum: Longint);
- { !! HERE IT IS !! }
- 1: (dwMinimum, dwMaximum: DWORD);
- 2: (dwReserved: array[0..5] of DWORD);
- { !! HERE IT IS !! }
- end;
- Metrics: record
- case Integer of
- 0: (cSteps: DWORD); { # of steps between min & max }
- 1: (cbCustomData: DWORD); { size in bytes of custom data }
- 2: (dwReserved: array[0..5] of DWORD);
- end;
- end;
- const
- badLineId = -1;
- badControlId = -1;
- NoItem = -1;
- type
- { D3: This lines rely on current Win32 API}
- {$IFDEF WIN32}
- TMMLineId = type integer;
- TMMControlId = type integer;
- TMMChannelIndex = Integer;
- TMMItemIndex = type Integer;
- TMMLineIndex = Integer;
- TMMControlIndex = Integer;
- TMMConnectionIndex = Integer;
- {$ENDIF}
- TMMComponentType = (ctDstDigital,ctDstHeadPhones,ctDstLine,
- ctDstMonitor,ctDstSpeakers,ctDstTelephone,
- ctDstUndefined,ctDstVoiceIn,ctDstWaveIn,
- ctSrcAnalog,ctSrcAux,ctSrcCD,ctSrcDigital,
- ctSrcLine,ctSrcMicrophone,ctSrcPCSpeaker,
- ctSrcSynthesizer,ctSrcTelephone,ctSrcUndefined,
- ctSrcWaveOut);
- TMMControlClass = (ccCustom,ccFader,ccList,ccMeter,ccNumber,
- ccSlider,ccSwitch,ccTime);
- TMMControlClasses = set of TMMControlClass;
- TMMControlType = (ctCustom,ctBass,ctEqualizer,ctFader,ctTreble,
- ctVolume,ctMixer,ctMultipleSelect,ctMux,
- ctSingleSelect,ctBooleanMeter,ctPeakMeter,
- ctSignerMeter,ctUnsignedMeter,ctDecibels,
- ctPercent,ctSigned,ctUnsigned,ctPan,ctQSoundPan,
- ctSlider,ctBoolean,ctButton,ctLoudness,ctMono,
- ctMute,ctOnOff,ctStereoEnh,ctMicroTime,ctMilliTime);
- TMMLineChangeEvent = procedure(Sender: TObject; LineId: TMMLineId) of object;
- TMMControlChangeEvent = procedure(Sender: TObject; LineId: TMMLineId; CtlId: TMMControlId) of object;
- {$IFNDEF BUILD_ACTIVEX}
- TMMComponent1 = TMMComponent;
- {$ELSE}
- TMMComponent1 = TMMNonVisualComponent;
- {$ENDIF}
- {-- TMMMixerDevice ------------------------------------------------------}
- TMMMixerDevice = class(TMMCustomAudioDevice)
- private
- FHandle : HMIXER;
- FCBWnd : HWND;
- FDevice : TMMCustomAudioDevice;
- FObserver : TMMObserver;
- FObservable : TMMObservable;
- FDummyInd : TMMLineIndex;
- FOnLineChange : TMMLineChangeEvent;
- FOnControlChange: TMMControlChangeEvent;
- procedure SetDevice(Value: TMMCustomAudioDevice);
- procedure DeviceNotify(Sender, Data: TObject);
- function StoreDeviceId: Boolean;
- function GetDestinations: TMMLineIndex;
- function GetDestination(Index: TMMLineIndex): TMMLineId;
- function GetMixerId: TMMDeviceId;
- procedure MixerWndProc(var Msg: TMessage);
- protected
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- procedure Changed; override;
- procedure UpdateDevice; override;
- procedure Open; override;
- procedure Close; override;
- procedure LineChanged(LineId: TMMLineId); virtual;
- procedure ControlChanged(CtlId: TMMControlId); virtual;
- procedure DoLineChange(LineId: TMMLineId); dynamic;
- procedure DoControlChange(LineId: TMMLineId; CtlId: TMMControlId); dynamic;
- { D3: This lines rely on current Win32 API}
- function GetLineInfo(var Info: TMixerLine; Flags: DWORD): Boolean;
- procedure GetControlValues(Id: TMMControlId; ItemSize: DWORD; Channels: Integer; Items: TMMItemIndex; Values: Pointer; Flags: DWORD);
- procedure SetControlValues(Id: TMMControlId; ItemSize: DWORD; Channels: Integer; Items: TMMItemIndex; Values: Pointer; Flags: DWORD);
- function GetControlInfo(var Info: TMixerLineControls; Flags: DWORD): Boolean;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure AddObserver(O: TMMObserver);
- procedure RemoveObserver(O: TMMObserver);
- function GetLineOfControl(CtlId: TMMControlId): TMMLineId;
- function GetLineInfoById(LineId: TMMLineId; var Info: TMixerLine): Boolean;
- function GetLineInfoByCompType(CompType: TMMComponentType; var Info: TMixerLine): Boolean;
- function GetLineInfoByTarget(Device: TMMCustomAudioDevice; var Info: TMixerLine): Boolean;
- function GetLineInfoByDestination(Dest: TMMLineIndex; var Info: TMixerLine): Boolean;
- function GetLineInfoBySource(Dest, Src: TMMLineIndex; var Info: TMixerLine): Boolean;
- function GetControlInfoById(ControlId: TMMControlId; var Info: TMixerControl): Boolean;
- function GetControlInfoByType(LineId: TMMLineId; ControlType: TMMControlType; var Info: TMixerControl): Boolean;
- function GetControlByType(LineId: TMMLineId; ControlType: TMMControlType): TMMControlId;
- procedure GetAllControls(LineId: TMMLineId; Controls: TMMControlIndex; P: PMixerControl);
- procedure GetBooleanControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PBoolean);
- procedure SetBooleanControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PBoolean);
- procedure GetSignedControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PInteger);
- procedure SetSignedControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PInteger);
- procedure GetUnsignedControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PCardinal);
- procedure SetUnsignedControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PCardinal);
- procedure GetItemsInfo(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Infos: PMixerControlDetailsListText);
- { If mixer is opened then get id of handle and update DeviceId if needed }
- property MixerId: TMMDeviceId read GetMixerId;
- property Destination[Index:TMMLineIndex]: TMMLineId read GetDestination;
- published
- property DeviceId stored StoreDeviceId;
- property Device: TMMCustomAudioDevice read FDevice write SetDevice;
- property Destinations: TMMLineIndex read GetDestinations write FDummyInd stored False;
- property OnLineChange: TMMLineChangeEvent read FOnLineChange write FOnLineChange;
- property OnControlChange: TMMControlChangeEvent read FOnControlChange write FOnControlChange;
- end;
- {-- TMMMixerChange --------------------------------------------------}
- TMMMixerChange = class(TMMObject)
- end;
- {-- TMMLineChange ---------------------------------------------------}
- TMMLineChange = class(TMMMixerChange)
- public
- LineId: TMMLineId;
- end;
- {-- TMMControlChange ------------------------------------------------}
- TMMControlChange = class(TMMMixerChange)
- public
- LineId : TMMLineId;
- ControlId: TMMControlId;
- end;
- {-- TMMMixerDeviceError ---------------------------------------------}
- EMMMixerDeviceError = class(EMMDeviceError)
- end;
- {-- TMMAudioLine ----------------------------------------------------}
- TMMLineSetup = (lsLineId,lsCompType,lsTarget);
- { D3: This lines rely on current Win32 API}
- TMMLineFlag = (cfActive,cfDisconnected,cfSource);
- TMMLineFlags = set of TMMLineFlag;
- {-- TMMLineInfo -----------------------------------------------------}
- TMMLineInfo = class(TPersistent)
- private
- FFlags : TMMLineFlags;
- FChannels : Integer;
- FConnections: Integer;
- FControls : Integer;
- FShortName : string;
- FName : string;
- FLDummy : Integer;
- FFDummy : TMMLineFlags;
- procedure SetDummyStr(const Value: string);
- public
- procedure Clear;
- published
- property Flags: TMMLineFlags read FFlags write FFDummy stored False;
- property Channels: TMMChannelIndex read FChannels write FLDummy stored False;
- property Connections: TMMConnectionIndex read FConnections write FLDummy stored False;
- property Controls: TMMControlIndex read FControls write FLDummy stored False;
- property ShortName: string read FShortName write SetDummyStr stored False;
- property Name: string read FName write SetDummyStr stored False;
- end;
- {-- TMMAudioLine ----------------------------------------------------}
- TMMAudioLine = class(TMMNonVisualComponent)
- private
- FLineId : TMMLineId;
- FDestinationId : TMMLineIndex;
- FDestLine : TMMAudioLine;
- FDestObserver : TMMObserver;
- FLineInfo : TMMLineInfo;
- FComponentType : TMMComponentType;
- FMixer : TMMMixerDevice;
- FObserver : TMMObserver;
- FLineSetup : TMMLineSetup;
- FTarget : TMMCustomAudioDevice;
- FTargetObserver : TMMObserver;
- FObservable : TMMObservable;
- FOnChange : TNotifyEvent;
- FOnControlChange: TMMControlChangeEvent;
- procedure SetMixer(Value: TMMMixerDevice);
- procedure MixerNotify(Sender, Data: TObject);
- procedure TargetNotify(Sender, Data: TObject);
- procedure DestNotify(Sender, Data: TObject);
- procedure SetDestLine(Value: TMMComponent1);
- function GetDestLine : TMMComponent1;
- procedure SetLineId(Value: TMMLineId);
- procedure SetComponentType(Value: TMMComponentType);
- procedure SetTarget(Value: TMMCustomAudioDevice);
- function StoreLineId: Boolean;
- function StoreComponentType: Boolean;
- function StoreTarget: Boolean;
- procedure SetLineInfo(const Info: TMMLineInfo);
- function GetConnections: TMMConnectionIndex;
- function GetConnection(Index: TMMConnectionIndex): TMMLineId;
- function GetControls: TMMControlIndex;
- function GetControl(Index: TMMControlIndex): TMMControlId;
- protected
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- procedure Changed; virtual;
- procedure DoChange; dynamic;
- procedure LineIdChanged; virtual;
- procedure ControlChanged(CtlId: TMMControlId); virtual;
- procedure DoControlChange(CtlId: TMMControlId); dynamic;
- procedure UpdateLine;
- procedure Loaded; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure AddObserver(O: TMMObserver);
- procedure RemoveObserver(O: TMMObserver);
- function GetLineInfoForSource(Source: TMMAudioLine; var Info : TMixerLine): Boolean;
- function ValidMixer: Boolean;
- property Connections: TMMConnectionIndex read GetConnections;
- property Connection[Index:TMMConnectionIndex]: TMMLineId read GetConnection;
- property Controls: TMMControlIndex read GetControls;
- property Control[Index:TMMControlIndex]: TMMControlId read GetControl;
- published
- property Mixer: TMMMixerDevice read FMixer write SetMixer;
- property LineId: TMMLineId read FLineId write SetLineId stored StoreLineId default badLineId;
- property ComponentType: TMMComponentType read FComponentType write SetComponentType stored StoreComponentType default Low(TMMComponentType);
- property Target: TMMCustomAudioDevice read FTarget write SetTarget stored StoreTarget;
- { TMMComponent because TMMAudioLine caused GPF }
- property DestLine: TMMComponent1 read GetDestLine write SetDestLine;
- property LineInfo: TMMLineInfo read FLineInfo write SetLineInfo stored False;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property OnControlChange: TMMControlChangeEvent read FOnControlChange write FOnControlChange;
- end;
- {-- TMMLineIDChange -------------------------------------------------}
- TMMLineIdChange = class(TMMMixerChange)
- end;
- EMMAudioLineError = class(Exception)
- end;
- TMMControlSetup = (csControlId, csControlType);
- { D3: This lines rely on current Win32 API}
- TMMControlFlag = (cfDisabled,cfMultiple,cfUniform);
- TMMControlFlags = set of TMMControlFlag;
- {-- TMMControlInfo --------------------------------------------------}
- TMMControlInfo = class(TPersistent)
- {$IFNDEF BUILD_ACTIVEX}
- private
- {$ELSE}
- public
- {$ENDIF}
- FFlags : TMMControlFlags;
- FMultipleItems : TMMItemIndex;
- FShortName : string;
- FName : string;
- FMinValue : Integer;
- FMaxValue : Integer;
- FSteps : Integer;
- FLDummy : Integer;
- FFDummy : TMMControlFlags;
- FIDummy : TMMItemIndex;
- procedure SetDummyStr(const Value: string);
- public
- procedure Clear;
- published
- property Flags: TMMControlFlags read FFlags write FFDummy stored False;
- property MultipleItems: TMMItemIndex read FMultipleItems write FIDummy stored False;
- property ShortName: string read FShortName write SetDummyStr stored False;
- property Name: string read FName write SetDummyStr stored False;
- property MinValue: Integer read FMinValue write FLDummy stored False;
- property MaxValue: Integer read FMaxValue write FLDummy stored False;
- property Steps: Integer read FSteps write FLDummy stored False;
- end;
- { D3: This lines rely on current Win32 API}
- TMMItemParam = DWord;
- 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
- for Result:= Low(TMMControlClass) to High(TMMControlClass) do
- if (CT and MIXERCONTROL_CT_CLASS_MASK) = CClasses[Result] then
- Exit;
- { TODO: Should be resource id }
- raise EMMMixerServiceError.Create('Undefined API control class');
- end;
- {------------------------------------------------------------------------}
- function IsControlTypeSingleSelect(CT: DWORD): Boolean;
- begin
- Result := MIXERCONTROL_CT_SC_LIST_SINGLE =
- (MIXERCONTROL_CT_SUBCLASS_MASK and CT);
- end;
- {== TMMMixerDevice ======================================================}
- constructor TMMMixerDevice.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FObserver := TMMObserver.Create;
- FObserver.OnNotify := DeviceNotify;
- FObservable := TMMObservable.Create;
- DeviceType := dtMixer;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- destructor TMMMixerDevice.Destroy;
- begin
- Device := nil;
- FObserver.Free;
- FObservable.Free;
- inherited Destroy;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.SetDevice(Value: TMMCustomAudioDevice);
- var
- WasActive: Boolean;
- begin
- if (Value <> nil) then
- if (Value.GetDeviceType = dtMixer) then
- { TODO: Should be resource id }
- raise EMMMixerDeviceError.Create('Mixer can''t reference mixer');
- if (Value <> FDevice) then
- begin
- WasActive:= Active;
- Close;
- if (FDevice <> nil) then
- FDevice.RemoveObserver(FObserver);
- FDevice:= Value;
- if (FDevice <> nil) then
- begin
- FDevice.AddObserver(FObserver);
- FDevice.FreeNotification(Self);
- end;
- UpdateDevice;
- Active:= WasActive;
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.DeviceNotify(Sender, Data: TObject);
- begin
- UpdateDevice;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited Notification(AComponent,Operation);
- if (Operation = opRemove) and (AComponent = FDevice) then
- Device := nil;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.UpdateDevice;
- begin
- if (FDevice <> nil) then
- DeviceId:= FDevice.MixerId;
- inherited UpdateDevice;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.Changed;
- var
- UpdChange: TMMDeviceChange;
- begin
- UpdChange:= TMMDeviceChange.Create;
- try
- FObservable.NotifyObservers(UpdChange);
- finally
- UpdChange.Free;
- end;
- inherited;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.StoreDeviceId: Boolean;
- begin
- if (FDevice <> nil) then
- Result := FDevice.MixerId <> MixerId
- else
- Result := DeviceId <> 0;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetDestinations: TMMLineIndex;
- var
- Caps: TMixerCaps;
- begin
- if ValidDevice then
- begin
- Check(mixerGetDevCaps(DeviceId, @Caps, SizeOf(Caps)));
- Result:= Caps.cDestinations;
- end
- else Result := 0;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.Open;
- begin
- if ValidDevice then
- begin
- FCBWnd:= AllocateHWnd(MixerWndProc);
- try
- Check(mixerOpen(@FHandle,DeviceId,FCBWnd,0,CALLBACK_WINDOW or MIXER_OBJECTF_MIXER));
- inherited Open;
- except
- DeAllocateHWnd(FCBWnd);
- FCBWnd:= 0;
- end
- end
- else
- { TODO: Should be resource id }
- raise EMMMixerDeviceError.Create('Device not valid');
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.Close;
- begin
- if FHandle <> 0 then
- begin
- Check(mixerClose(FHandle));
- FHandle:= 0;
- end;
- if FCBWnd <> 0 then
- begin
- DeAllocateHWnd(FCBWnd);
- FCBWnd:= 0;
- end;
- inherited Close;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.MixerWndProc(var Msg: TMessage);
- begin
- with Msg do
- begin
- try
- if (Msg = MM_MIXM_LINE_CHANGE) and (wParam = FHandle) then
- LineChanged(lParam)
- else if (Msg = MM_MIXM_CONTROL_CHANGE) and (wParam = FHandle) then
- ControlChanged(lParam)
- else
- Result:= DefWindowProc(FCBWnd, Msg, wParam, lParam);
- except
- Application.HandleException(Self);
- end;
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.LineChanged(LineId: TMMLineId);
- var
- Chg: TMMLineChange;
- begin
- Chg:= TMMLineChange.Create;
- try
- Chg.LineId := LineId;
- FObservable.NotifyObservers(Chg);
- finally
- Chg.Free;
- end;
- DoLineChange(LineId);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.ControlChanged(CtlId: TMMControlId);
- var
- Chg : TMMControlChange;
- LineId: TMMLineId;
- begin
- LineId := GetLineOfControl(CtlId);
- Chg := TMMControlChange.Create;
- try
- Chg.ControlId:= CtlId;
- Chg.LineId := LineId;
- FObservable.NotifyObservers(Chg);
- finally
- Chg.Free;
- end;
- DoControlChange(LineId,CtlId);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.DoLineChange(LineId: TMMLineId);
- begin
- if Assigned(FOnLineChange) then FOnLineChange(Self,LineId);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.DoControlChange(LineId: TMMLineId; CtlId: TMMControlId);
- begin
- if Assigned(FOnControlChange) then FOnControlChange(Self,LineId,CtlId);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetMixerId: TMMDeviceId;
- var
- Res: UINT;
- begin
- if FHandle <> 0 then
- begin
- Check(mixerGetId(FHandle, Res, MIXER_OBJECTF_HMIXER));
- Result := Res;
- { If device id was changed, FHandle will be still correct but }
- { we should check for id }
- if (Result <> DeviceId) then
- begin
- { Just update class member }
- SetDeviceIdDirect(Result);
- { Notify updates }
- Changed;
- end;
- end
- else Result := DeviceId;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.AddObserver(O: TMMObserver);
- begin
- FObservable.AddObserver(O);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.RemoveObserver(O: TMMObserver);
- begin
- if (FObservable <> nil) then
- FObservable.RemoveObserver(O);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetLineOfControl(CtlId: TMMControlId): TMMLineId;
- var
- Ctls: TMixerLineControls;
- Ctl : TMixerControl;
- begin
- { We should do this call manually instead of use GetControlInfoById
- because we need to access dwLineId member of TMixerLineControls record }
- Ctls.cbStruct := SizeOf(Ctls);
- Ctls.dwControlId := CtlId;
- Ctls.cControls := 1;
- Ctls.cbmxCtrl := sizeof(TMixerControl);
- Ctls.pamxCtrl := @Ctl;
- Check(mixerGetLineControls(MixerId, @Ctls, MIXER_GETLINECONTROLSF_ONEBYID or MIXER_OBJECTF_MIXER));
- Result := Ctls.dwLineId;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetLineInfoById(LineId: TMMLineId; var Info: TMixerLine): Boolean;
- begin
- Info.dwLineId := LineId;
- Result := GetLineInfo(Info,MIXER_GETLINEINFOF_LINEID);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetLineInfoByCompType(CompType: TMMComponentType; var Info: TMixerLine): Boolean;
- begin
- Info.dwComponentType:= CompTypeToAPI(CompType);
- Result := GetLineInfo(Info,MIXER_GETLINEINFOF_COMPONENTTYPE);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetLineInfoByDestination(Dest: TMMLineIndex; var Info: TMixerLine): Boolean;
- begin
- Info.dwDestination := Dest;
- Result := GetLineInfo(Info,MIXER_GETLINEINFOF_DESTINATION);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetLineInfoBySource(Dest, Src: TMMLineIndex; var Info: TMixerLine): Boolean;
- begin
- Info.dwDestination := Dest;
- Info.dwSource := Src;
- Result := GetLineInfo(Info,MIXER_GETLINEINFOF_SOURCE);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetLineInfo(var Info: TMixerLine; Flags: DWORD): Boolean;
- begin
- Info.cbStruct:= SizeOf(Info);
- Result:= CheckExcl(mixerGetLineInfo(MixerId, @Info, MIXER_OBJECTF_MIXER or Flags), [MIXERR_INVALLINE,MMSYSERR_NODRIVER,MMSYSERR_INVALPARAM])
- = MMSYSERR_NOERROR;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetLineInfoByTarget(Device: TMMCustomAudioDevice; var Info: TMixerLine): Boolean;
- begin
- with Device.DeviceCaps do
- begin
- Info.Target.dwType := DeviceTypeToTarget(Device.GetDeviceType);
- Info.Target.wMid := ManufacturerId;
- Info.Target.wPid := ProductId;
- Info.Target.vDriverVersion := MakeVersion(VerMajor,VerMinor);
- StrPLCopy(Info.Target.szPName, ProductName, MAXPNAMELEN);
- Result:= GetLineInfo(Info, MIXER_GETLINEINFOF_TARGETTYPE);
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetControlInfoById(ControlId: TMMControlId; var Info: TMixerControl): Boolean;
- var
- Ctls: TMixerLineControls;
- begin
- Ctls.dwControlId:= ControlId;
- Ctls.cControls := 1;
- Ctls.cbmxCtrl := SizeOf(Info);
- Ctls.pamxCtrl := @Info;
- Result:= GetControlInfo(Ctls, MIXER_GETLINECONTROLSF_ONEBYID);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetControlInfoByType(LineId: TMMLineId; ControlType: TMMControlType; var Info: TMixerControl): Boolean;
- var
- Ctls: TMixerLineControls;
- begin
- Ctls.dwLineId := LineId;
- Ctls.dwControlType := ControlTypeToAPI(ControlType);
- Ctls.cControls := 1;
- Ctls.cbmxCtrl := SizeOf(Info);
- Ctls.pamxCtrl := @Info;
- Result:= GetControlInfo(Ctls, MIXER_GETLINECONTROLSF_ONEBYTYPE);
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.GetAllControls(LineId: TMMLineId; Controls: TMMControlIndex; P: PMixerControl);
- var
- Ctls: TMixerLineControls;
- begin
- Ctls.dwLineId := LineId;
- Ctls.cControls := Controls;
- Ctls.cbmxCtrl := SizeOf(P^);
- Ctls.pamxCtrl := PMixerControlA(P);
- if not GetControlInfo(Ctls, MIXER_GETLINECONTROLSF_ALL) then
- { TODO: Should be resource id }
- raise EMMMixerDeviceError.Create('Error requesting all controls');
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetControlInfo(var Info: TMixerLineControls; Flags: DWORD): Boolean;
- begin
- Info.cbStruct:= SizeOf(Info);
- Result:= CheckExcl(mixerGetLineControls(MixerId,@Info,MIXER_OBJECTF_MIXER or Flags), [MIXERR_INVALCONTROL,MIXERR_INVALLINE,MMSYSERR_NODRIVER])
- = MMSYSERR_NOERROR;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetControlByType(LineId: TMMLineId; ControlType: TMMControlType): TMMControlId;
- var
- Info: TMixerControl;
- begin
- if GetControlInfoByType(LineId, ControlType, Info) then
- Result:= Info.dwControlId
- else
- Result:= badControlId;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- function TMMMixerDevice.GetDestination(Index: TMMLineIndex): TMMLineId;
- var
- Info: TMixerLine;
- begin
- if GetLineInfoByDestination(Index,Info) then
- Result:= Info.dwLineId
- else
- Result:= badLineId;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.SetBooleanControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PBoolean);
- var
- Buf, P : PMixerControlDetailsBoolean;
- i : Integer;
- N : Integer;
- begin
- N := Max(Channels,1) * Max(Items,1);
- Buf:= GlobalAllocMem(SizeOf(P^) * N);
- try
- P:= Buf;
- for i:= 0 to N - 1 do
- begin
- P^.fValue:= Ord(Values^);
- Inc(P);
- Inc(Values);
- end;
- SetControlValues(Id, SizeOf(P^), Channels, Items, Buf, MIXER_SETCONTROLDETAILSF_VALUE);
- finally
- GlobalFreeMem(Pointer(Buf));
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.GetBooleanControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PBoolean);
- var
- Buf, P : PMixerControlDetailsBoolean;
- i : Integer;
- N : Integer;
- begin
- N := Max(Channels,1) * Max(Items,1);
- Buf:= GlobalAllocMem(SizeOf(P^) * N);
- try
- P:= Buf;
- GetControlValues(Id, SizeOf(P^), Channels, Items, P, MIXER_GETCONTROLDETAILSF_VALUE);
- for i:= 0 to N - 1 do
- begin
- Values^:= Boolean(P^.fValue);
- Inc(P);
- Inc(Values);
- end;
- finally
- GlobalFreeMem(Pointer(Buf));
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.SetSignedControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PInteger);
- var
- Buf, P : PMixerControlDetailsSigned;
- i : Integer;
- N : Integer;
- begin
- N := Max(Channels,1) * Max(Items,1);
- Buf:= GlobalAllocMem(SizeOf(P^) * N);
- try
- P:= Buf;
- for i:= 0 to N - 1 do
- begin
- P^.lValue:= Values^;
- Inc(P);
- Inc(Values);
- end;
- SetControlValues(Id, SizeOf(P^), Channels, Items, Buf, MIXER_SETCONTROLDETAILSF_VALUE);
- finally
- GlobalFreeMem(Pointer(Buf));
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.GetSignedControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PInteger);
- var
- Buf, P : PMixerControlDetailsSigned;
- i : Integer;
- N : Integer;
- begin
- N := Max(Channels,1) * Max(Items,1);
- Buf:= GlobalAllocMem(SizeOf(P^) * N);
- try
- P:= Buf;
- GetControlValues(Id, SizeOf(P^), Channels, Items, P, MIXER_GETCONTROLDETAILSF_VALUE);
- for i:= 0 to N - 1 do
- begin
- Values^:= P^.lValue;
- Inc(P);
- Inc(Values);
- end;
- finally
- GlobalFreeMem(Pointer(Buf));
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.SetUnsignedControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PCardinal);
- var
- Buf, P : PMixerControlDetailsUnsigned;
- i : Integer;
- N : Integer;
- begin
- N := Max(Channels,1) * Max(Items,1);
- Buf:= GlobalAllocMem(SizeOf(P^) * N);
- try
- P:= Buf;
- for i:= 0 to N - 1 do
- begin
- P^.dwValue:= Values^;
- Inc(P);
- Inc(Values);
- end;
- SetControlValues(Id, SizeOf(P^), Channels, Items, Buf, MIXER_SETCONTROLDETAILSF_VALUE);
- finally
- GlobalFreeMem(Pointer(Buf));
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.GetUnsignedControl(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: PCardinal);
- var
- Buf, P : PMixerControlDetailsUnsigned;
- i : Integer;
- N : Integer;
- begin
- N := Max(Channels,1) * Max(Items,1);
- Buf:= GlobalAllocMem(SizeOf(P^) * N);
- try
- P:= Buf;
- GetControlValues(Id, SizeOf(P^), Channels, Items, P, MIXER_GETCONTROLDETAILSF_VALUE);
- for i:= 0 to N - 1 do
- begin
- Values^:= P^.dwValue;
- Inc(P);
- Inc(Values);
- end;
- finally
- GlobalFreeMem(Pointer(Buf));
- end;
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.GetItemsInfo(Id: TMMControlId; Channels: TMMChannelIndex; Items: TMMItemIndex; Infos: PMixerControlDetailsListText);
- var
- Details: TMixerControlDetails;
- begin
- FillChar(Details,SizeOf(Details),0);
- Details.cbStruct := SizeOf(Details);
- Details.cbDetails := SizeOf(Infos^);
- Details.paDetails := Infos;
- Details.dwControlId := Id;
- Details.cMultipleItems := Items;
- Details.cChannels := Channels;
- Check(mixerGetControlDetails(MixerId, @Details, MIXER_OBJECTF_MIXER or MIXER_GETCONTROLDETAILSF_LISTTEXT));
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.GetControlValues(Id: TMMControlId; ItemSize: DWORD; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: Pointer; Flags: DWORD);
- var
- Details : TMixerControlDetails;
- begin
- FillChar(Details,SizeOf(Details),0);
- Details.cbStruct := SizeOf(Details);
- Details.cbDetails := ItemSize;
- Details.paDetails := Values;
- Details.dwControlId := Id;
- Details.cMultipleItems := Items;
- Details.cChannels := Channels;
- Check(mixerGetControlDetails(MixerId, @Details, MIXER_OBJECTF_MIXER or Flags));
- end;
- {-- TMMMixerDevice ------------------------------------------------------}
- procedure TMMMixerDevice.SetControlValues(Id: TMMControlId; ItemSize: DWORD; Channels: TMMChannelIndex; Items: TMMItemIndex; Values: Pointer; Flags: DWORD);
- var
- Details : TMixerControlDetails;
- begin
- FillChar(Details,SizeOf(Details),0);
- Details.cbStruct := SizeOf(Details);
- Details.cbDetails := ItemSize;
- Details.paDetails := Values;
- Details.dwControlId := Id;
- Details.cMultipleItems := Items;
- Details.cChannels := Channels;
- Check(mixerSetControlDetails(MixerId, @Details, MIXER_OBJECTF_MIXER or Flags));
- end;
- {== TMMLineInfo =========================================================}
- procedure TMMLineInfo.SetDummyStr(const Value: string);
- begin
- ;
- end;
- {-- TMMLineInfo ---------------------------------------------------------}
- procedure TMMLineInfo.Clear;
- begin
- FFlags := [];
- FChannels := 0;
- FConnections := 0;
- FControls := 0;
- FShortName := '';
- FName := '';
- end;
- {== TMMAudioLine ========================================================}
- constructor TMMAudioLine.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FLineInfo := TMMLineInfo.Create;
- FObserver := TMMObserver.Create;
- FObserver.OnNotify := MixerNotify;
- FTargetObserver := TMMObserver.Create;
- FTargetObserver.OnNotify:= TargetNotify;
- FDestObserver := TMMObserver.Create;
- FDestObserver.OnNotify := DestNotify;
- FLineId := badLineId;
- FObservable := TMMObservable.Create;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- destructor TMMAudioLine.Destroy;
- begin
- FObserver.Free;
- FTargetObserver.Free;
- FDestObserver.Free;
- FObservable.Free;
- FObservable:= nil;
- FLineInfo.Free;
- inherited Destroy;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited Notification(AComponent,Operation);
- if (Operation = opRemove) then
- begin
- if (AComponent = FMixer) then
- Mixer:= nil
- else if (AComponent = FTarget) then
- Target:= nil
- else if (AComponent = FDestLine) then
- DestLine := nil
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.SetMixer(Value: TMMMixerDevice);
- begin
- if (Value <> FMixer) then
- begin
- if (FMixer <> nil) then
- FMixer.RemoveObserver(FObserver);
- FMixer:= Value;
- if (FMixer <> nil) then
- begin
- FMixer.AddObserver(FObserver);
- FMixer.FreeNotification(Self);
- end;
- UpdateLine;
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.SetLineId(Value: TMMLineId);
- begin
- if (Value <> FLineId) then
- begin
- FLineId := Value;
- FLineSetup := lsLineId;
- UpdateLine;
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.SetComponentType(Value: TMMComponentType);
- begin
- if (Value <> FComponentType) then
- begin
- FComponentType := Value;
- FLineSetup := lsCompType;
- UpdateLine;
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.SetTarget(Value: TMMCustomAudioDevice);
- begin
- if (Value <> nil) and (Value.GetDeviceType = dtMixer) then
- { TODO: Should be resource id }
- raise EMMMixerDeviceError.Create('Can''t target to mixer');
- if Value <> FTarget then
- begin
- if FTarget <> nil then
- FTarget.RemoveObserver(FTargetObserver);
- FTarget:= Value;
- if FTarget <> nil then
- begin
- FTarget.AddObserver(FTargetObserver);
- FTarget.FreeNotification(Self);
- end;
- FLineSetup := lsTarget;
- UpdateLine;
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.StoreLineId: Boolean;
- begin
- Result:= (FLineSetup = lsLineId) and (FLineId <> badLineId);
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.StoreComponentType: Boolean;
- begin
- Result := (FLineSetup = lsCompType) and (FComponentType <> Low(TMMComponentType));
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.StoreTarget: Boolean;
- begin
- Result := (FLineSetup = lsTarget) and (FTarget <> nil);
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.SetLineInfo(const Info: TMMLineInfo);
- begin
- ;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.GetConnections: TMMConnectionIndex;
- begin
- Result := LineInfo.Connections;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.GetConnection(Index: TMMConnectionIndex): TMMLineId;
- var
- Info: TMixerLine;
- begin
- if not InRange(Index, 0, Connections - 1) then
- { TODO: Should be resource id }
- raise EMMAudioLineError.Create('Connection index out of range');
- if ValidMixer then
- begin
- if Mixer.GetLineInfoBySource(FDestinationId, Index, Info) then
- begin
- Result:= Info.dwLineId;
- Exit;
- end;
- end;
- Result:= badLineId;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.GetControls: TMMControlIndex;
- begin
- Result := LineInfo.Controls;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.GetControl(Index: TMMControlIndex): TMMControlId;
- var
- P, R: PMixerControl;
- Size: Integer;
- begin
- if not InRange(Index, 0, Controls - 1) then
- { TODO: Should be resource id }
- raise EMMAudioLineError.Create('Control index out of range');
- if not ValidMixer then
- begin
- Result:= badControlId;
- Exit;
- end;
- Size:= SizeOf(P^)*Controls;
- GetMem(P,Size);
- try
- Mixer.GetAllControls(LineId,Controls,P);
- R:= P;
- Inc(R,Index);
- Result:= R^.dwControlId;
- finally
- FreeMem(P,Size);
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.ValidMixer: Boolean;
- begin
- Result:= (FMixer <> nil) and FMixer.ValidDevice;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.UpdateLine;
- var
- LineInfo: TMixerLine;
- Ok: Boolean;
- begin
- if csLoading in ComponentState then
- Exit;
- FDestinationId:= badLineId;
- Ok := False;
- if ValidMixer then
- begin
- if FDestLine <> nil then
- if FDestLine.Mixer = Mixer then
- Ok := FDestLine.GetLineInfoForSource(Self,LineInfo)
- else
- Ok := False
- else
- case FLineSetup of
- lsLineId : Ok:= (FLineId <> badLineId) and Mixer.GetLineInfoById(FLineId, LineInfo);
- lsCompType : Ok:= Mixer.GetLineInfoByCompType(FComponentType, LineInfo);
- lsTarget : Ok:= Mixer.GetLineInfoByTarget(FTarget, LineInfo);
- end;
- if Ok then
- begin
- FLineId := LineInfo.dwLineId;
- FComponentType := APIToCompType(LineInfo.dwComponentType);
- with FLineInfo do
- begin
- FFlags := APIToLineFlags(LineInfo.fdwLine);
- FChannels := LineInfo.cChannels;
- FConnections := LineInfo.cConnections;
- FControls := LineInfo.cControls;
- if not (cfSource in FFlags) then
- FDestinationId := LineInfo.dwDestination
- else
- FDestinationId := badLineId;
- FShortName := LineInfo.szShortName;
- FName := LineInfo.szName;
- end;
- end
- else
- begin
- FLineId := badLineId;
- FLineInfo.Clear;
- end;
- end;
- LineIdChanged;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.Loaded;
- begin
- inherited Loaded;
- UpdateLine;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.MixerNotify(Sender, Data: TObject);
- begin
- if Data is TMMLineChange then
- begin
- if (Data as TMMLineChange).LineId = FLineId then
- Changed;
- end
- else if Data is TMMControlChange then
- begin
- if (Data as TMMControlChange).LineId = FLineId then
- ControlChanged((Data as TMMControlChange).ControlId)
- end
- else if Data is TMMDeviceChange then
- begin
- UpdateLine;
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.TargetNotify(Sender, Data: TObject);
- begin
- UpdateLine;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.DestNotify(Sender, Data: TObject);
- begin
- if (Data <> nil) and (Data is TMMLineIdChange) then
- UpdateLine;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.SetDestLine(Value: TMMComponent1);
- begin
- if (Value <> nil) and not (Value is TMMAudioLine) then
- { TODO: Should be resource id }
- raise EMMMixerDeviceError.Create('DestLine should be TMMAudioLine');
- if FDestLine <> Value then
- begin
- if FDestLine <> nil then
- FDestLine.RemoveObserver(FDestObserver);
- FDestLine := Value as TMMAudioLine;
- if FDestLine <> nil then
- begin
- FDestLine.AddObserver(FTargetObserver);
- FDestLine.FreeNotification(Self);
- end;
- UpdateLine;
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.GetDestLine: TMMComponent1;
- begin
- Result := FDestLine;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.Changed;
- var
- Chg: TMMLineChange;
- begin
- Chg:= TMMLineChange.Create;
- try
- Chg.LineId:= LineId;
- FObservable.NotifyObservers(Chg);
- finally
- Chg.Free;
- end;
- DoChange;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.LineIdChanged;
- var
- Chg: TMMLineIdChange;
- begin
- Chg:= TMMLineIdChange.Create;
- try
- FObservable.NotifyObservers(Chg);
- finally
- Chg.Free;
- end;
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.DoChange;
- begin
- if Assigned(FOnChange) then FOnChange(Self);
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.ControlChanged(CtlId: TMMControlId);
- var
- Chg: TMMControlChange;
- begin
- Chg:= TMMControlChange.Create;
- try
- Chg.LineId := LineId;
- Chg.ControlId := CtlId;
- FObservable.NotifyObservers(Chg);
- finally
- Chg.Free;
- end;
- DoControlChange(CtlId);
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.DoControlChange(CtlId: TMMControlId);
- begin
- if Assigned(FOnControlChange) then FOnControlChange(Self, FLineId, CtlId);
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.AddObserver(O: TMMObserver);
- begin
- FObservable.AddObserver(O);
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- procedure TMMAudioLine.RemoveObserver(O: TMMObserver);
- begin
- if FObservable <> nil then
- FObservable.RemoveObserver(O);
- end;
- {-- TMMAudioLine --------------------------------------------------------}
- function TMMAudioLine.GetLineInfoForSource(Source: TMMAudioLine; var Info : TMixerLine): Boolean;
- var
- i : Integer;
- Ok: Boolean;
- function CompTypeOk: Boolean;
- begin
- Result := APIToCompType(Info.dwComponentType) = Source.FComponentType;
- end;
- function TargetOk: Boolean;
- begin
- if Source.Target <> nil then
- with Source.Target.DeviceCaps do
- begin
- Result := (Info.Target.dwType = DeviceTypeToTarget(Source.Target.GetDeviceType)) and
- (Info.Target.wMid = ManufacturerId) and
- (Info.Target.wPid = ProductId) and
- (Info.Target.vDriverVersion = MakeVersion(VerMajor,VerMinor)) and
- (StrComp(Info.Target.szPName, PChar(ProductName)) = 0);
- end
- else
- Result := False;
- end;
- begin
- Result := False;
- Ok := False;
- if csLoading in ComponentState then
- Exit;
- if ValidMixer and
- (LineId <> badLineId) and
- not (cfSource in LineInfo.Flags) then
- begin
- case Source.FLineSetup of
- lsLineId : Ok:= (Source.FLineId <> badLineId) and Mixer.GetLineInfoById(Source.FLineId, Info);
- lsCompType : Ok:= Mixer.GetLineInfoByCompType(Source.FComponentType, Info);
- lsTarget : Ok:= Mixer.GetLineInfoByTarget(Source.FTarget, Info);
- end;
- if not Ok then
- Exit;
- if Info.dwDestination = LineId then
- begin
- Result := True;
- Exit;
- end;
- if Source.FLineSetup = lsLineId then
- Exit;
- for i := 0 to Connections - 1 do
- if Mixer.GetLineInfoBySource(FDestinationId, i, Info) then
- if ((Source.FLineSetup = lsCompType) and CompTypeOk) or
- ((Source.FLineSetup = lsTarget) and TargetOk) then begin
- Result := True;
- Exit;
- end;
- end;
- end;
- {== TMMControlInfo ======================================================}
- procedure TMMControlInfo.SetDummyStr(const Value: string);
- begin
- ;
- end;
- {-- TMMControlInfo ------------------------------------------------------}
- procedure TMMControlInfo.Clear;
- begin
- FFlags := [];
- FMultipleItems := 0;
- FShortName := '';
- FName := '';
- FMinValue := 0;
- FMaxValue := 0;
- FSteps := 0;
- end;
- {== TMMCustomMixerControl ===============================================}
- constructor TMMCustomMixerControl.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FControlInfo := TMMControlInfo.Create;
- FControlId := badControlId;
- FObserver := TMMObserver.Create;
- FObserver.OnNotify := LineNotify;
- FObservable := TMMObservable.Create;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- destructor TMMCustomMixerControl.Destroy;
- begin
- FObserver.Free;
- FControlInfo.Free;
- FObservable.Free;
- FObservable:= nil;
- inherited Destroy;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.AddObserver(O: TMMObserver);
- begin
- FObservable.AddObserver(O);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.RemoveObserver(O: TMMObserver);
- begin
- if FObservable <> nil then
- FObservable.RemoveObserver(O);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.CalcParams(C: TMMChannel; Item: TMMItemIndex; var Ch: TMMChannelIndex; var It: TMMItemIndex);
- begin
- NeedId;
- if C = chBoth then
- Ch:= Min(Channels,1)
- else
- Ch:= Channels;
- if Item = NoItem then
- It:= 0
- else if InRange(Item,0,Items-1) then
- It:= Items
- else
- { TODO: Should be resource id }
- raise EMMMixerControlError.Create('Item index out of range');
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetChannelSigned(C: TMMChannel; Item: TMMItemIndex): Integer;
- var
- P : PIntArray;
- Size: Integer;
- Ch : TMMChannelIndex;
- It : TMMItemIndex;
- begin
- CalcParams(C,Item,Ch,It);
- Size:= SizeOf(P^)*Max(Ch,1)*Max(It,1);
- GetMem(P,Size);
- try
- Mixer.GetSignedControl(ControlId,Ch,It,@P^[0]);
- Result:= P^[ValueIndex(C,Item)];
- finally
- FreeMem(P,Size);
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetChannelSigned(C: TMMChannel; Item: TMMItemIndex; Value: Integer);
- var
- P : PIntArray;
- Size: Integer;
- Ch : TMMChannelIndex;
- It : TMMItemIndex;
- begin
- CalcParams(C,Item,Ch,It);
- Size:= SizeOf(P^)*Max(Ch,1)*Max(It,1);
- GetMem(P,Size);
- try
- Mixer.GetSignedControl(ControlId,Ch,It,@P^[0]);
- P^[ValueIndex(C,Item)]:= Value;
- Mixer.SetSignedControl(ControlId,Ch,It,@P^[0]);
- finally
- FreeMem(P,Size);
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetChannelUnsigned(C: TMMChannel; Item: TMMItemIndex): Cardinal;
- var
- P : PCardinalArray;
- Size: Integer;
- Ch : TMMChannelIndex;
- It : TMMItemIndex;
- begin
- CalcParams(C,Item,Ch,It);
- Size:= SizeOf(P^)*Max(Ch,1)*Max(It,1);
- GetMem(P,Size);
- try
- Mixer.GetUnsignedControl(ControlId,Ch,It,@P^[0]);
- Result:= P^[ValueIndex(C,Item)];
- finally
- FreeMem(P,Size);
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetChannelUnsigned(C: TMMChannel; Item: TMMItemIndex; Value: Cardinal);
- var
- P : PCardinalArray;
- Size: Integer;
- Ch : TMMChannelIndex;
- It : TMMItemIndex;
- begin
- CalcParams(C,Item,Ch,It);
- Size:= SizeOf(P^)*Max(Ch,1)*Max(It,1);
- GetMem(P,Size);
- try
- Mixer.GetUnsignedControl(ControlId,Ch,It,@P^[0]);
- P^[ValueIndex(C,Item)]:= Value;
- Mixer.SetUnsignedControl(ControlId,Ch,It,@P^[0]);
- finally
- FreeMem(P,Size);
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetChannelBoolean(C: TMMChannel; Item: TMMItemIndex): Boolean;
- var
- P : PBooleanArray;
- Size: Integer;
- Ch : TMMChannelIndex;
- It : TMMItemIndex;
- begin
- CalcParams(C,Item,Ch,It);
- Size:= SizeOf(P^)*Max(Ch,1)*Max(It,1);
- GetMem(P,Size);
- try
- Mixer.GetBooleanControl(ControlId,Ch,It,@P^[0]);
- Result:= P^[ValueIndex(C,Item)];
- finally
- FreeMem(P,Size);
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetChannelBoolean(C: TMMChannel; Item: TMMItemIndex; Value: Boolean);
- var
- P : PBooleanArray;
- Size: Integer;
- Ch : TMMChannelIndex;
- It : TMMItemIndex;
- i : TMMItemIndex;
- begin
- CalcParams(C,Item,Ch,It);
- Size:= SizeOf(P^)*Max(Ch,1)*Max(It,1);
- GetMem(P,Size);
- try
- Mixer.GetBooleanControl(ControlId,Ch,It,@P^[0]);
- { If controls is single select, then we should clear other items first }
- if (Items > 0) and IsControlTypeSingleSelect(ControlTypeToAPI(ControlType)) then
- for i := 0 to Items - 1 do
- P^[ValueIndex(C,i)] := False;
- P^[ValueIndex(C,Item)]:= Value;
- Mixer.SetBooleanControl(ControlId,Ch,It,@P^[0]);
- finally
- FreeMem(P,Size);
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetItemInfo(Index: TMMItemIndex): TMMItemInfo;
- var
- P, R : PMixerControlDetailsListText;
- Size : Integer;
- begin
- NeedId;
- if not (cfMultiple in ControlInfo.Flags) then
- { TODO: Should be resource id }
- raise EMMMixerControlError.Create('Item info requested from non-multiple control');
- FillChar(Result,SizeOf(Result),0);
- if not InRange(Index,0,Items-1) then
- { TODO: Should be resource id }
- raise EMMMixerControlError.Create('Item index out of range');
- Size:= SizeOf(P^) * Max(Items,1) * Max(Channels,1);
- GetMem(P,Size);
- try
- Mixer.GetItemsInfo(ControlId,Channels,Items,P);
- R:= P;
- Inc(R,Index*Max(Channels,1));
- with R^ do
- begin
- Result.Val1:= dwParam1;
- Result.Val2:= dwParam2;
- Result.Name:= szName;
- end;
- finally
- FreeMem(P,Size);
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.UpdateControl;
- var
- Info: TMixerControl;
- Ok : Boolean;
- begin
- if csLoading in ComponentState then
- begin
- FControlClass:= ControlClassOfType(ControlTypeToAPI(FControlType));
- Exit;
- end;
- Ok:= False;
- if ValidMixer then
- begin
- case FControlSetup of
- csControlId : Ok:= Mixer.GetControlInfoById(FControlId, Info);
- csControlType : Ok:= Mixer.GetControlInfoByType(LineId, FControlType, Info);
- end;
- if Ok and ValidControl(Info) then
- begin
- FControlId := Info.dwControlId;
- FControlType:= APIToControlType(Info.dwControlType);
- with FControlInfo do
- begin
- FFlags := APIToControlFlags(Info.fdwControl);
- FMultipleItems := Info.cMultipleItems;
- FShortName := Info.szShortName;
- FName := Info.szName;
- FMinValue := Info.Bounds.lMinimum;
- FMaxValue := Info.Bounds.lMaximum;
- FSteps := Info.Metrics.cSteps;
- end;
- end
- else
- begin
- FControlId := badControlId;
- FControlInfo.Clear;
- end;
- end;
- FControlClass:= ControlClassOfType(ControlTypeToAPI(FControlType));
- ControlIdChanged;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.Loaded;
- begin
- inherited Loaded;
- UpdateControl;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.LineNotify(Sender, Data: TObject);
- begin
- if Data is TMMControlChange then
- begin
- with (Data as TMMControlChange) do
- if (LineId = Self.LineId) and (ControlId = Self.ControlId) then
- Self.Changed;
- end
- else if Data is TMMLineIdChange then
- UpdateControl;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited Notification(AComponent,Operation);
- if Operation = opRemove then
- begin
- if AComponent = AudioLine then
- AudioLine:= nil;
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetAudioLine(Value: TMMAudioLine);
- begin
- if Value <> FAudioLine then
- begin
- if FAudioLine <> nil then
- FAudioLine.RemoveObserver(FObserver);
- FAudioLine:= Value;
- if FAudioLine <> nil then
- begin
- FAudioLine.AddObserver(FObserver);
- FAudioLine.FreeNotification(Self);
- end;
- UpdateControl;
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetControlId(Value: TMMControlId);
- begin
- if Value <> FControlId then
- begin
- FControlId := Value;
- FControlSetup := csControlId;
- UpdateControl;
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetControlType(Value: TMMControlType);
- begin
- if Value <> FControlType then
- begin
- FControlType := Value;
- FControlSetup := csControlType;
- UpdateControl;
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetMixer: TMMMixerDevice;
- begin
- if (FAudioLine <> nil) and FAudioLine.ValidMixer then
- Result := FAudioLine.Mixer
- else
- Result := nil;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.NeedMixer;
- begin
- if Mixer = nil then
- { TODO: Should be resouce id }
- raise EMMDeviceError.Create('Mixer required for this operation');
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.NeedId;
- begin
- NeedMixer;
- if FControlId = badControlId then
- { TODO: Should be resouce id }
- raise EMMDeviceError.Create('Control not valid');
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetLineId: TMMLineId;
- begin
- NeedMixer;
- Result := FAudioLine.LineId;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.Changed;
- var
- CtlChg: TMMControlChange;
- begin
- CtlChg:= TMMControlChange.Create;
- try
- if ValidMixer then
- CtlChg.LineId := LineId
- else
- CtlChg.LineId := badLineId;
- CtlChg.ControlId := ControlId;
- FObservable.NotifyObservers(CtlChg);
- finally
- CtlChg.Free;
- end;
- DoChange;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.ControlIdChanged;
- var
- CtlChg: TMMControlIdChange;
- begin
- CtlChg:= TMMControlIdChange.Create;
- try
- FObservable.NotifyObservers(CtlChg);
- finally
- CtlChg.Free;
- end;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.DoChange;
- begin
- if System.Assigned(FOnChange) then
- FOnChange(Self);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.StoreControlId: Boolean;
- begin
- Result:= (FControlSetup = csControlId) and (FControlId <> badLineId);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetControlInfo(const Value: TMMControlInfo);
- begin
- ;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetBoolean: Boolean;
- begin
- NeedId;
- Mixer.GetBooleanControl(ControlId, Min(Channels,1), 0, @Result);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetBoolean(Value: Boolean);
- begin
- NeedId;
- Mixer.SetBooleanControl(ControlId, Min(Channels,1), 0, @Value);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetUnsigned: Cardinal;
- begin
- NeedId;
- Mixer.GetUnsignedControl(ControlId, Min(Channels,1), 0, @Result);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetUnsigned(Value: Cardinal);
- begin
- NeedId;
- Mixer.SetUnsignedControl(ControlId, Min(Channels,1), 0, @Value);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetSigned: Integer;
- begin
- NeedId;
- Mixer.GetSignedControl(ControlId, Min(Channels,1), 0, @Result);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- procedure TMMCustomMixerControl.SetSigned(Value: Integer);
- begin
- NeedId;
- Mixer.SetSignedControl(ControlId, Min(Channels,1), 0, @Value);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetAvailable: Boolean;
- begin
- Result:= ValidMixer and (ControlId <> badControlId);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetChannels: Integer;
- begin
- if Mixer = nil then
- Result:= 0
- else if cfUniform in ControlInfo.Flags then
- Result:= 1
- else
- Result:= AudioLine.LineInfo.Channels;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetItems: TMMItemIndex;
- begin
- if Mixer = nil then
- Result:= 0
- else
- Result:= ControlInfo.MultipleItems;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.ValueIndex(C: TMMChannel; Item: TMMItemIndex): Integer;
- begin
- if (Channels < 2) or (C = chBoth) then
- Result:= Max(Item,0) + 0
- else if (C = chLeft) then
- Result:= Max(Channels,1) * Max(Item,0) + 0
- else
- Result:= Max(Channels,1) * Max(Item,0) + 1;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.ValidMixer : Boolean;
- begin
- Result:= (Mixer <> nil) and (FAudioLine.LineId <> badLineId);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.CanModify : Boolean;
- begin
- Result:= Available and not (cfDisabled in ControlInfo.Flags);
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetItemForLine(Line: TMMAudioLine): TMMItemIndex;
- var
- i : TMMItemIndex;
- begin
- if (Line <> nil) and (Line.LineId <> badLineId) and
- Available and (cfMultiple in ControlInfo.Flags) and
- (ControlType in [ctMixer,ctMux]) then
- for i := 0 to Items - 1 do
- if ItemInfo[i].Val1 = Line.LineId then
- begin
- Result := i;
- Exit;
- end;
- Result := NoItem;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.ValidControl(const Info: TMixerControl): Boolean;
- begin
- Result:= True;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.GetControlSetup: TMMControlSetup;
- begin
- Result:= FControlSetup;
- end;
- {-- TMMCustomMixerControl -----------------------------------------------}
- function TMMCustomMixerControl.StoreControlType: Boolean;
- begin
- Result:= (GetControlSetup = csControlType) and (ControlType <> Low(TMMControlType));
- end;
- {== TMMVolumeControl ====================================================}
- constructor TMMVolumeControl.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- ControlType:= ctVolume;
- end;
- {-- TMMVolumeControl ----------------------------------------------------}
- procedure TMMVolumeControl.SetUnsigned(Value: Cardinal);
- begin
- SetChannelUnsigned(chLeft,NoItem,Trunc(Value*Pan(chLeft)));
- SetChannelUnsigned(chRight,NoItem,Trunc(Value*Pan(chRight)));
- end;
- {-- TMMVolumeControl ----------------------------------------------------}
- procedure TMMVolumeControl.SetSigned(Value: Integer);
- begin
- SetChannelSigned(chLeft,NoItem,Trunc(Value*Pan(chLeft)));
- SetChannelSigned(chRight,NoItem,Trunc(Value*Pan(chRight)));
- end;
- {-- TMMVolumeControl ----------------------------------------------------}
- procedure TMMVolumeControl.SetChannelSigned(C: TMMChannel; Item: TMMItemIndex; Value: Integer);
- begin
- if C = chBoth then
- begin
- inherited SetChannelSigned(chLeft,Item,Trunc(Value*Pan(chLeft)));
- inherited SetChannelSigned(chRight,Item,Trunc(Value*Pan(chRight)));
- end
- else inherited SetChannelSigned(C,Item,Value);
- end;
- {-- TMMVolumeControl ----------------------------------------------------}
- procedure TMMVolumeControl.SetChannelUnsigned(C: TMMChannel; Item: TMMItemIndex; Value: Cardinal);
- begin
- if C = chBoth then
- begin
- inherited SetChannelUnsigned(chLeft,Item,Trunc(Value*Pan(chLeft)));
- inherited SetChannelUnsigned(chRight,Item,Trunc(Value*Pan(chRight)));
- end
- else inherited SetChannelUnsigned(C,Item,Value);
- end;
- {-- TMMVolumeControl ----------------------------------------------------}
- function TMMVolumeControl.Pan(C:TMMChannel):Extended;
- begin
- if ((FPanValue <= 0) and (C = chLeft)) or
- ((FPanValue >= 0) and (C = chRight)) then
- Result:= 1
- else if C = chLeft then
- Result:= (MaxRightPan - FPanValue) / MaxRightPan
- else
- Result:= (MaxLeftPan - FPanValue) / MaxLeftPan;
- end;
- {-- TMMVolumeControl ----------------------------------------------------}
- procedure TMMVolumeControl.SetPanValue(Value: Integer);
- begin
- if FPanValue <> Value then
- begin
- FPanValue:= Value;
- if Available then
- AsSigned:= AsSigned;
- end;
- end;
- {-- TMMVolumeControl ----------------------------------------------------}
- function TMMVolumeControl.ValidControl(const Info: TMixerControl): Boolean;
- begin
- Result:= Info.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
- end;
- {== TMMPanControl =======================================================}
- constructor TMMPanControl.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- ControlType := ctPan;
- FSimulate := True;
- FSimActive := False;
- FObserver := TMMObserver.Create;
- FObserver.OnNotify := VolumeNotify;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- destructor TMMPanControl.Destroy;
- begin
- FObserver.Free;
- inherited Destroy;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.UpdatePan;
- var
- WasActive: Boolean;
- begin
- if csLoading in ComponentState then
- Exit;
- WasActive := FSimActive;
- FSimActive:= not inherited GetAvailable and FSimulate and (FVolume <> nil) and
- FVolume.Available and not (cfUniform in FVolume.ControlInfo.Flags) and
- (FVolume.Channels > 1);
- if FSimActive then
- with ControlInfo do
- begin
- FFlags := [cfUniform];
- FMultipleItems := 0;
- FShortName := 'Pan';
- FName := 'Simulated pan';
- FMinValue := MaxLeftPan;
- FMaxValue := MaxRightPan;
- FSteps := 0;
- end;
- if FSimActive <> WasActive then
- begin
- inherited ControlIdChanged;
- if not WasActive then
- UpdatePanValue;
- end;
- if FVolume <> nil then
- begin
- if FSimActive then
- FVolume.PanValue:= AsSigned
- else
- FVolume.PanValue:= 0;
- end;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.UpdateControl;
- begin
- UpdatePan;
- if not FSimActive then
- inherited UpdateControl;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.SetControl(Value:TMMVolumeControl);
- begin
- if Value <> FVolume then
- begin
- if FVolume <> nil then
- begin
- FVolume.RemoveObserver(FObserver);
- FVolume.PanValue:= 0;
- end;
- FVolume:= Value;
- if FVolume <> nil then
- begin
- FVolume.AddObserver(FObserver);
- FVolume.FreeNotification(Self);
- end;
- UpdateControl;
- end;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.SetSimulate(Value:Boolean);
- begin
- if FSimulate <> Value then
- begin
- FSimulate:= Value;
- UpdateControl;
- end;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.VolumeNotify(Sender,Data:TObject);
- begin
- if Data is TMMControlIdChange then
- UpdateControl
- else
- UpdatePanValue;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited Notification(AComponent,Operation);
- if Operation = opRemove then
- if AComponent = FVolume then
- VolumeControl:= nil;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.UpdatePanValue;
- var
- Left, Right: Integer;
- begin
- if FSimActive then
- begin
- Left := VolumeControl.GetChannelSigned(chLeft,NoItem);
- Right := VolumeControl.GetChannelSigned(chRight,NoItem);
- if Left = 0 then
- if Right = 0 then
- else
- FValue:= MaxRightPan
- else
- if Right = 0 then
- FValue:= MaxLeftPan
- else
- FValue:= Trunc(MaxRightPan * (Right - Left) / Max(Right,Left));
- { Set directly because setting to prop causes updates of volume controls }
- VolumeControl.FPanValue:= FValue;
- Changed;
- end;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.SetSigned(Value: Integer);
- begin
- if FSimActive then
- begin
- FValue:= Value;
- UpdateVolumePan;
- end
- else inherited SetSigned(Value);
- end;
- {-- TMMPanControl -------------------------------------------------------}
- function TMMPanControl.GetSigned: Integer;
- begin
- if FSimActive then
- Result:= FValue
- else
- Result:= inherited GetSigned;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- function TMMPanControl.GetChannelSigned(C: TMMChannel; Item: TMMItemIndex): Integer;
- begin
- if FSimActive then
- Result:= FValue
- else
- Result:= inherited GetChannelSigned(C,Item);
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.SetChannelSigned(C: TMMChannel; Item: TMMItemIndex; Value: Integer);
- begin
- if FSimActive then
- begin
- FValue:= Value;
- UpdateVolumePan;
- end
- else inherited SetChannelSigned(C,Item,Value);
- end;
- {-- TMMPanControl -------------------------------------------------------}
- procedure TMMPanControl.UpdateVolumePan;
- begin
- if FSimActive then
- FVolume.PanValue:= FValue;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- function TMMPanControl.GetAvailable: Boolean;
- begin
- if FSimActive then
- Result:= True
- else
- Result:= inherited GetAvailable;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- function TMMPanControl.ValidControl(const Info: TMixerControl): Boolean;
- begin
- Result:= Info.dwControlType = MIXERCONTROL_CONTROLTYPE_PAN;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- function TMMPanControl.GetChannels: Integer;
- begin
- Result:= 1;
- end;
- {-- TMMPanControl -------------------------------------------------------}
- function TMMPanControl.GetItems: TMMItemIndex;
- begin
- Result:= 0;
- end;
- {== Property service ====================================================}
- function ControlIdToIdent(Id: LongInt; var S: string) : Boolean;
- begin
- Result := False;
- if Id = badControlId then
- begin
- S := 'badControlId';
- Result := True;
- end;
- end;
- {------------------------------------------------------------------------}
- function IdentToControlId(const S: string; var Id: LongInt) : Boolean;
- begin
- Result := False;
- if CompareText(S, 'badControlId') = 0 then
- begin
- Result := True;
- Id := badControlId;
- end;
- end;
- {------------------------------------------------------------------------}
- function LineIdToIdent(Id: LongInt; var S: string) : Boolean;
- begin
- Result := False;
- if Id = badLineId then
- begin
- S := 'badLineId';
- Result := True;
- end;
- end;
- {------------------------------------------------------------------------}
- function IdentToLineId(const S: string; var Id: LongInt) : Boolean;
- begin
- Result := False;
- if CompareText(S, 'badLineId') = 0 then
- begin
- Result := True;
- Id := badLineId;
- end;
- end;
- {------------------------------------------------------------------------}
- function ItemIndexToIdent(Id: LongInt; var S: string) : Boolean;
- begin
- Result := False;
- if Id = NoItem then
- begin
- S := 'NoItem';
- Result := True;
- end;
- end;
- {------------------------------------------------------------------------}
- function IdentToItemIndex(const S: string; var Id: LongInt) : Boolean;
- begin
- Result := False;
- if CompareText(S, 'NoItem') = 0 then
- begin
- Result := True;
- Id := NoItem;
- end;
- end;
- initialization
- RegisterIntegerConsts(TypeInfo(TMMControlId),IdentToControlId,ControlIdToIdent);
- RegisterIntegerConsts(TypeInfo(TMMLineId),IdentToLineId,LineIdToIdent);
- RegisterIntegerConsts(TypeInfo(TMMItemIndex),IdentToItemIndex,ItemIndexToIdent);
- end.