Componentes.Terceros.jcl/official/1.96/examples/windows/multimedia/MultimediaDemoMain.pas

556 lines
20 KiB
ObjectPascal

unit MultimediaDemoMain;
interface
{$I jcl.inc}
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, MMSystem, JclMultimedia;
type
TMainForm = class(TForm)
PageControl: TPageControl;
TabSheet1: TTabSheet;
Label2: TLabel;
OpenDriveBtn: TButton;
CloseDriveBtn: TButton;
MediaPresentBtn: TButton;
AudioInfoBtn: TButton;
AudioInfoMemo: TMemo;
GroupBox1: TGroupBox;
Label1: TLabel;
DriveComboBox: TComboBox;
DefaultDriveCheckBox: TCheckBox;
TabSheet2: TTabSheet;
MixerTreeView: TTreeView;
Label3: TLabel;
MixerDetailListView: TListView;
Label4: TLabel;
GroupBox2: TGroupBox;
SpeakersMuteCheckBox: TCheckBox;
SaveMixerBtn: TButton;
SaveDialog: TSaveDialog;
procedure FormCreate(Sender: TObject);
procedure OpenDriveBtnClick(Sender: TObject);
procedure CloseDriveBtnClick(Sender: TObject);
procedure MediaPresentBtnClick(Sender: TObject);
procedure AudioInfoBtnClick(Sender: TObject);
procedure DefaultDriveCheckBoxClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure MixerTreeViewCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
procedure MixerTreeViewChange(Sender: TObject; Node: TTreeNode);
procedure SpeakersMuteCheckBoxClick(Sender: TObject);
procedure SaveMixerBtnClick(Sender: TObject);
private
FComponentTypes: TStringList;
FControlTypes: TStringList;
FMixer: TJclMixer;
procedure BuildDrives;
procedure BuildMixerTree;
procedure BuildTypesList;
function GetSelectedDrive: Char;
procedure SaveMixerToFile(const FileName: string);
procedure UpdateMixerDetails(MixerObject: TObject);
procedure UpdateMixerControl(MixerHandle: HMIXER; ControlID: DWORD);
procedure UpdateMixerLine(MixerHandle: HMIXER; LineID: DWORD);
procedure UpdateSelectedMixerInfo;
procedure UpdateMixerSpeakerControls;
procedure WMMmMixmControlChange(var Message: TMessage); message MM_MIXM_CONTROL_CHANGE;
procedure WMMmMixmLineChange(var Message: TMessage); message MM_MIXM_LINE_CHANGE;
function GetSelectedMixerTreeObject: TObject;
public
function ComponentTypeConstToString(ComponentType: DWORD): string;
function ControlTypeConstToString(ControlType: DWORD): string;
property SelectedDrive: Char read GetSelectedDrive;
property SelectedMixerTreeObject: TObject read GetSelectedMixerTreeObject;
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
uses
JclFileUtils, JclStrings, JclSysUtils;
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
FComponentTypes := TStringList.Create;
FControlTypes := TStringList.Create;
BuildTypesList;
FMixer := TJclMixer.Create(Handle);
BuildDrives;
BuildMixerTree;
UpdateMixerSpeakerControls;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FreeAndNil(FComponentTypes);
FreeAndNil(FControlTypes);
FreeAndNil(FMixer);
end;
procedure TMainForm.BuildTypesList;
begin
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_UNDEFINED', Pointer(MIXERLINE_COMPONENTTYPE_DST_UNDEFINED));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_DIGITAL', Pointer(MIXERLINE_COMPONENTTYPE_DST_DIGITAL));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_LINE', Pointer(MIXERLINE_COMPONENTTYPE_DST_LINE));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_MONITOR', Pointer(MIXERLINE_COMPONENTTYPE_DST_MONITOR));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_SPEAKERS', Pointer(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_HEADPHONES', Pointer(MIXERLINE_COMPONENTTYPE_DST_HEADPHONES));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_TELEPHONE', Pointer(MIXERLINE_COMPONENTTYPE_DST_TELEPHONE));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_WAVEIN', Pointer(MIXERLINE_COMPONENTTYPE_DST_WAVEIN));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_DST_VOICEIN', Pointer(MIXERLINE_COMPONENTTYPE_DST_VOICEIN));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED', Pointer(MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_DIGITAL', Pointer(MIXERLINE_COMPONENTTYPE_SRC_DIGITAL));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_LINE', Pointer(MIXERLINE_COMPONENTTYPE_SRC_LINE));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE', Pointer(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER', Pointer(MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC', Pointer(MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE', Pointer(MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER', Pointer(MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT', Pointer(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY', Pointer(MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY));
FComponentTypes.AddObject('MIXERLINE_COMPONENTTYPE_SRC_ANALOG', Pointer(MIXERLINE_COMPONENTTYPE_SRC_ANALOG));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_CUSTOM', Pointer(MIXERCONTROL_CONTROLTYPE_CUSTOM));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_BOOLEANMETER', Pointer(MIXERCONTROL_CONTROLTYPE_BOOLEANMETER));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_SIGNEDMETER', Pointer(MIXERCONTROL_CONTROLTYPE_SIGNEDMETER));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_PEAKMETER', Pointer(MIXERCONTROL_CONTROLTYPE_PEAKMETER));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER', Pointer(MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_BOOLEAN', Pointer(MIXERCONTROL_CONTROLTYPE_BOOLEAN));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_ONOFF', Pointer(MIXERCONTROL_CONTROLTYPE_ONOFF));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_MUTE', Pointer(MIXERCONTROL_CONTROLTYPE_MUTE));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_MONO', Pointer(MIXERCONTROL_CONTROLTYPE_MONO));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_LOUDNESS', Pointer(MIXERCONTROL_CONTROLTYPE_LOUDNESS));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_STEREOENH', Pointer(MIXERCONTROL_CONTROLTYPE_STEREOENH));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_BUTTON', Pointer(MIXERCONTROL_CONTROLTYPE_BUTTON));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_DECIBELS', Pointer(MIXERCONTROL_CONTROLTYPE_DECIBELS));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_SIGNED', Pointer(MIXERCONTROL_CONTROLTYPE_SIGNED));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_UNSIGNED', Pointer(MIXERCONTROL_CONTROLTYPE_UNSIGNED));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_PERCENT', Pointer(MIXERCONTROL_CONTROLTYPE_PERCENT));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_SLIDER', Pointer(MIXERCONTROL_CONTROLTYPE_SLIDER));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_PAN', Pointer(MIXERCONTROL_CONTROLTYPE_PAN));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_QSOUNDPAN', Pointer(MIXERCONTROL_CONTROLTYPE_QSOUNDPAN));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_FADER', Pointer(MIXERCONTROL_CONTROLTYPE_FADER));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_VOLUME', Pointer(MIXERCONTROL_CONTROLTYPE_VOLUME));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_BASS', Pointer(MIXERCONTROL_CONTROLTYPE_BASS));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_TREBLE', Pointer(MIXERCONTROL_CONTROLTYPE_TREBLE));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_EQUALIZER', Pointer(MIXERCONTROL_CONTROLTYPE_EQUALIZER));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_SINGLESELECT', Pointer(MIXERCONTROL_CONTROLTYPE_SINGLESELECT));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_MUX', Pointer(MIXERCONTROL_CONTROLTYPE_MUX));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT', Pointer(MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_MIXER', Pointer(MIXERCONTROL_CONTROLTYPE_MIXER));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_MICROTIME', Pointer(MIXERCONTROL_CONTROLTYPE_MICROTIME));
FControlTypes.AddObject('MIXERCONTROL_CONTROLTYPE_MILLITIME', Pointer(MIXERCONTROL_CONTROLTYPE_MILLITIME));
end;
function TMainForm.ComponentTypeConstToString(ComponentType: DWORD): string;
var
I: Integer;
begin
Result := '';
for I := 0 to FComponentTypes.Count - 1 do
if DWORD(FComponentTypes.Objects[I]) = ComponentType then
begin
Result := FComponentTypes[I];
Break;
end;
end;
function TMainForm.ControlTypeConstToString(ControlType: DWORD): string;
var
I: Integer;
begin
Result := '';
for I := 0 to FControlTypes.Count - 1 do
if DWORD(FControlTypes.Objects[I]) = ControlType then
begin
Result := FControlTypes[I];
Break;
end;
end;
//==================================================================================================
// CD audio
//==================================================================================================
procedure TMainForm.BuildDrives;
var
D: Char;
DriveStr: string;
begin
for D := 'A' to 'Z' do
begin
DriveStr := D + ':\';
if GetDriveType(PChar(DriveStr)) = DRIVE_CDROM then
DriveComboBox.Items.Add(D);
end;
if DriveComboBox.Items.Count > 0 then
DriveComboBox.ItemIndex := 0;
end;
procedure TMainForm.DefaultDriveCheckBoxClick(Sender: TObject);
begin
DriveComboBox.Enabled := not DefaultDriveCheckBox.Checked;
end;
function TMainForm.GetSelectedDrive: Char;
begin
if DefaultDriveCheckBox.Checked then
Result := #0
else
Result := DriveComboBox.Text[1];
end;
procedure TMainForm.OpenDriveBtnClick(Sender: TObject);
begin
Screen.Cursor := crHourGlass;
try
OpenCloseCdDrive(True, SelectedDrive);
finally
Screen.Cursor := crDefault;
end;
end;
procedure TMainForm.CloseDriveBtnClick(Sender: TObject);
begin
Screen.Cursor := crHourGlass;
try
OpenCloseCdDrive(False, SelectedDrive);
finally
Screen.Cursor := crDefault;
end;
end;
procedure TMainForm.MediaPresentBtnClick(Sender: TObject);
begin
Screen.Cursor := crHourGlass;
try
ShowMessage(BooleanToStr(IsMediaPresentInDrive(SelectedDrive)));
finally
Screen.Cursor := crDefault;
end;
end;
procedure TMainForm.AudioInfoBtnClick(Sender: TObject);
var
TotalTimeStr: string;
begin
Screen.Cursor := crHourGlass;
AudioInfoMemo.Lines.BeginUpdate;
try
AudioInfoMemo.Lines.Add('Product : ' + GetCdInfo(miProduct, SelectedDrive));
AudioInfoMemo.Lines.Add('Identity : ' + GetCdInfo(miIdentity, SelectedDrive));
AudioInfoMemo.Lines.Add('Universal Product Code : ' + GetCdInfo(miUPC, SelectedDrive));
TotalTimeStr := GetCDAudioTrackList(AudioInfoMemo.Lines, True, SelectedDrive);
AudioInfoMemo.Lines.Add('Total time: ' + TotalTimeStr);
finally
AudioInfoMemo.Lines.EndUpdate;
Screen.Cursor := crDefault;
end;
AudioInfoMemo.Lines.Add('');
end;
//==================================================================================================
// Audio mixer
//==================================================================================================
procedure TMainForm.BuildMixerTree;
var
DeviceIndex, DestionationIndex, SourceIndex, LineControlIndex: Integer;
DeviceNode, DestionationNode, SourceNode: TTreeNode;
Device: TJclMixerDevice;
Destination: TJclMixerDestination;
SourceLine: TJclMixerSource;
LineControl: TJclMixerLineControl;
begin
with MixerTreeView do
begin
Items.BeginUpdate;
Screen.Cursor := crHourGlass;
try
Items.Clear;
for DeviceIndex := 0 to FMixer.DeviceCount - 1 do
begin
Device := FMixer.Devices[DeviceIndex];
DeviceNode := Items.AddChildObjectFirst(nil, Device.ProductName, Device);
for DestionationIndex := 0 to Device.DestinationCount - 1 do
begin
Destination := Device.Destinations[DestionationIndex];
DestionationNode := Items.AddChildObjectFirst(DeviceNode, Destination.Name, Destination);
for LineControlIndex := 0 to Destination.LineControlCount - 1 do
begin
LineControl := Destination.LineControls[LineControlIndex];
Items.AddChildObjectFirst(DestionationNode, LineControl.Name, LineControl);
end;
for SourceIndex := 0 to Destination.SourceCount - 1 do
begin
SourceLine := Destination.Sources[SourceIndex];
SourceNode := Items.AddChildObjectFirst(DestionationNode, SourceLine.Name, SourceLine);
for LineControlIndex := 0 to SourceLine.LineControlCount - 1 do
begin
LineControl := SourceLine.LineControls[LineControlIndex];
Items.AddChildObjectFirst(SourceNode, LineControl.Name, LineControl);
end;
end;
end;
end;
FullExpand;
if Items.Count > 0 then
begin
Selected := Items.GetFirstNode;
Selected.MakeVisible;
end;
finally
Items.EndUpdate;
Screen.Cursor := crDefault;
end;
end;
end;
function TMainForm.GetSelectedMixerTreeObject: TObject;
begin
if MixerTreeView.Selected <> nil then
Result := TObject(MixerTreeView.Selected.Data)
else
Result := nil;
end;
procedure TMainForm.SaveMixerToFile(const FileName: string);
var
List: TStringList;
I, D: Integer;
Node: TTreeNode;
C: Char;
begin
List := TStringList.Create;
MixerDetailListView.Items.BeginUpdate;
try
for I := 0 to MixerTreeView.Items.Count - 1 do
begin
Node := MixerTreeView.Items[I];
UpdateMixerDetails(TObject(Node.Data));
case Node.Level of
0: C := ' ';
1: C := '=';
2: C := '+';
3: C := '-';
else
C := '!';
end;
List.Add(Format('%*s%s %s', [Node.Level * 2, '', Node.Text, StringOfChar(C, 119 - Node.Level * 2 - Length(Node.Text))]));
with MixerDetailListView.Items do
for D := 0 to Count - 1 do
begin
List.Add(Format('%*s%s=%s', [Node.Level * 2, '', Item[D].Caption, Item[D].SubItems[0]]));
end;
List.Add('');
end;
List.SaveToFile(FileName);
Node := MixerTreeView.Selected;
if Assigned(Node) then
UpdateMixerDetails(TObject(Node.Data))
else
UpdateMixerDetails(nil);
finally
MixerDetailListView.Items.EndUpdate;
List.Free;
end;
end;
procedure TMainForm.UpdateMixerDetails(MixerObject: TObject);
procedure AddLine(const ItemName, Value: string);
begin
with MixerDetailListView.Items.Add do
begin
Caption := ItemName;
SubItems.Add(Value);
end;
end;
procedure BuildMixerDeviceDetails(Device: TJclMixerDevice);
begin
with Device do
begin
AddLine('Handle', IntToHex(Handle, 8));
AddLine('Mid', IntToHex(Capabilities.wMid, 4));
AddLine('Pid', IntToHex(Capabilities.wPid, 4));
with WordRec(LongRec(Capabilities.vDriverVersion).Lo) do
AddLine('Driver version', FormatVersionString(Hi, Lo));
AddLine('Support', IntToHex(Capabilities.fdwSupport, 8));
end;
end;
procedure BuildMixerLineDetails(Line: TJclMixerLine);
var
DisplayName: string;
begin
with Line do
begin
DisplayName := ComponentString;
if DisplayName = '' then
DisplayName := Format('(%.8x)', [LineInfo.dwComponentType]);
AddLine('Component type', Format('%s [%s]', [DisplayName, ComponentTypeConstToString(LineInfo.dwComponentType)]));
AddLine('ID', IntToHex(ID, 8));
AddLine('Channels', IntToStr(LineInfo.cChannels));
AddLine('Connections', IntToStr(LineInfo.cConnections));
AddLine('Target name', LineInfo.Target.szPname);
end;
end;
procedure BuildMixerDestinationDetails(Destination: TJclMixerDestination);
begin
BuildMixerLineDetails(Destination);
end;
procedure BuildMixerSourceDetails(Source: TJclMixerSource);
begin
BuildMixerLineDetails(Source);
end;
procedure BuildMixerLineControlDetails(LineControl: TJclMixerLineControl);
begin
with LineControl do
begin
AddLine('ID', IntToHex(ControlInfo.dwControlID, 8));
AddLine('Control type', Format('%.8x [%s]', [ControlInfo.dwControlType, ControlTypeConstToString(ControlInfo.dwControlType)]));
AddLine('Disabled', BooleanToStr(IsDisabled));
AddLine('List', BooleanToStr(IsList));
AddLine('Multiple', BooleanToStr(IsMultiple));
AddLine('Uniform', BooleanToStr(IsUniform));
AddLine('Multiple items', IntToHex(ControlInfo.cMultipleItems, 8));
if not IsMultiple then
AddLine('Uniform value', IntToHex(UniformValue, 8));
AddLine('Minimum', IntToHex(ControlInfo.Bounds.lMinimum, 8));
AddLine('Maximum', IntToHex(ControlInfo.Bounds.lMaximum, 8));
AddLine('Steps', IntToHex(ControlInfo.Metrics.cSteps, 8));
AddLine('Value', ValueString);
AddLine('List text', ListText.CommaText);
end;
end;
begin
with MixerDetailListView do
begin
Items.BeginUpdate;
try
Items.Clear;
if MixerObject is TJclMixerDevice then
BuildMixerDeviceDetails(TJclMixerDevice(MixerObject))
else
if MixerObject is TJclMixerDestination then
BuildMixerDestinationDetails(TJclMixerDestination(MixerObject))
else
if MixerObject is TJclMixerSource then
BuildMixerSourceDetails(TJclMixerSource(MixerObject))
else
if MixerObject is TJclMixerLineControl then
BuildMixerLineControlDetails(TJclMixerLineControl(MixerObject));
finally
Items.EndUpdate;
end;
end;
end;
procedure TMainForm.UpdateMixerControl(MixerHandle: HMIXER; ControlID: DWORD);
var
Control: TJclMixerLineControl;
begin
Control := FMixer.LineControlByID[MixerHandle, ControlID];
if Control <> nil then
begin
if Control = SelectedMixerTreeObject then
UpdateSelectedMixerInfo;
end;
end;
procedure TMainForm.UpdateMixerLine(MixerHandle: HMIXER; LineID: DWORD);
var
Line: TJclMixerLine;
begin
Line := FMixer.LineByID[MixerHandle, LineID];
if Line <> nil then
begin
if Line = SelectedMixerTreeObject then
UpdateSelectedMixerInfo;
if Line.LineInfo.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS then
UpdateMixerSpeakerControls;
end;
end;
procedure TMainForm.UpdateSelectedMixerInfo;
begin
UpdateMixerDetails(SelectedMixerTreeObject);
end;
procedure TMainForm.UpdateMixerSpeakerControls;
begin
SpeakersMuteCheckBox.Checked := FMixer.SpeakersMute;
end;
procedure TMainForm.MixerTreeViewCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
NodeObject: TObject;
begin
NodeObject := TObject(Node.Data);
if NodeObject is TJclMixerDevice then
Sender.Canvas.Font.Style := [fsBold]
else
if NodeObject is TJclMixerDestination then
begin
Sender.Canvas.Font.Style := [fsBold];
if not (cdsFocused in State) then
Sender.Canvas.Font.Color := clRed;
end
else
if NodeObject is TJclMixerSource then
begin
Sender.Canvas.Font.Style := [fsBold];
if not (cdsFocused in State) then
Sender.Canvas.Font.Color := clBlue;
end;
end;
procedure TMainForm.MixerTreeViewChange(Sender: TObject; Node: TTreeNode);
begin
UpdateMixerDetails(TObject(Node.Data));
end;
procedure TMainForm.SpeakersMuteCheckBoxClick(Sender: TObject);
begin
FMixer.SpeakersMute := SpeakersMuteCheckBox.Checked;
end;
procedure TMainForm.SaveMixerBtnClick(Sender: TObject);
begin
SaveDialog.FileName := 'Mixer.txt';
if SaveDialog.Execute then
SaveMixerToFile(SaveDialog.FileName);
end;
procedure TMainForm.WMMmMixmControlChange(var Message: TMessage);
begin
UpdateMixerControl(Message.WParam, Message.LParam);
end;
procedure TMainForm.WMMmMixmLineChange(var Message: TMessage);
begin
UpdateMixerLine(Message.WParam, Message.LParam);
end;
end.