Author: Tomas Rutkauskas
Is there a way, like the Windows Volume Control, to get the current
volume output... not the Volume settings (loudness), but how "loud" the
playing sound is? The Volume Control has a "red-to-green" bar that show
the volume output... how could this be done?
Answer:
Here's some code that will retrieve a handle to the meter attached to
the WaveOut source of the speaker line, if there is one:
1 var
2 MixerControl: TMixerControl;
3 MixerControlDetails: TMixerControlDetails;
4 MixerControlDetailsSigned: TMixerControlDetailsSigned;
5 Mixer: THandle;
6 MixerLine: TMixerLine;
7 MixerLineControls: TMixerLineControls;
8 PeakMeter: DWord;
9 Rslt: DWord;
10 SourceCount: Cardinal;
11 WaveOut: DWord;
12 I: Integer;
13 X: Integer;
14 Y: Integer;
15 begin
16 Rslt := mixerOpen(@Mixer, 0, 0, 0, 0);
17 if Rslt <> 0 then
18 raise Exception.CreateFmt('Can''t open mixer (%d)', [Rslt]);
19 FillChar(MixerLine, SizeOf(MixerLine), 0);
20 MixerLine.cbStruct := SizeOf(MixerLine);
21 MixerLine.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
22 Rslt := mixerGetLineInfo(Mixer, @MixerLine,
23 MIXER_GETLINEINFOF_COMPONENTTYPE);
24 if Rslt <> 0 then
25 raise Exception.CreateFmt('Can''t find speaker line (%d)', [Rslt]);
26 SourceCount := MixerLine.cConnections;
27 WaveOut := $FFFFFFFF;
28 for I := 0 to SourceCount - 1 do
29 begin
30 MixerLine.dwSource := I;
31 Rslt := mixerGetLineInfo(Mixer, @MixerLine,
32 MIXER_GETLINEINFOF_SOURCE);
33 if Rslt <> 0 then
34 raise Exception.CreateFmt('Can''t get source line (%d)', [Rslt]);
35 if MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT then
36 begin
37 WaveOut := MixerLine.dwLineId;
38 Break;
39 end;
40 end;
41 if WaveOut = $FFFFFFFF then
42 raise Exception.Create('Can''t find wave out device');
43 FillChar(MixerLineControls, SizeOf(MixerLineControls), 0);
44 with MixerLineControls do
45 begin
46 cbStruct := SizeOf(MixerLineControls);
47 dwLineId := WaveOut;
48 dwControlType := MIXERCONTROL_CONTROLTYPE_PEAKMETER;
49 cControls := 1;
50 cbmxctrl := SizeOf(TMixerControl);
51 pamxctrl := @MixerControl;
52 end;
53 Rslt := mixerGetLineControls(Mixer, @MixerLineControls,
54 MIXER_GETLINECONTROLSF_ONEBYTYPE);
55 if Rslt <> 0 then
56 raise Exception.CreateFmt('Can''t find peak meter control (%d)',
57 [Rslt]);
58 PeakMeter := MixerControl.dwControlID;
59
60 // at this point, I have the meter control ID, so I can
61 // repeatedly query its value and plot the resulting data
62 // on a canvas
63
64 X := 0;
65 FillChar(MixerControlDetails, SizeOf(MixerControlDetails), 0);
66 with MixerControlDetails do
67 begin
68 cbStruct := SizeOf(MixerControlDetails);
69 dwControlId := PeakMeter;
70 cChannels := 1;
71 cbDetails := SizeOf(MixerControlDetailsSigned);
72 paDetails := @MixerControlDetailsSigned;
73 end;
74 repeat
75 Sleep(10);
76 Rslt := mixerGetControlDetails(Mixer, @MixerControlDetails,
77 MIXER_GETCONTROLDETAILSF_VALUE);
78 if Rslt <> 0 then
79 raise Exception.CreateFmt('Can''t get control details (%d)',
80 [Rslt]);
81 Application.ProcessMessages;
82 Inc(X);
83 Y := 300 - Round(300 * Abs(MixerControlDetailsSigned.lValue) /
84 32768);
85 with Canvas do
86 begin
87 MoveTo(X, 0);
88 Pen.Color := clBtnFace;
89 LineTo(X, 300);
90 Pen.Color := clWindowText;
91 LineTo(X, Y);
92 end;
93 until X > 500;
94
95 // don't forget to close the mixer handle when you're done
96
97 Rslt := mixerClose(Mixer);
98 if Rslt <> 0 then
99 raise Exception.CreateFmt('Can''t close mixer (%d)', [Rslt]);
100 end;
|