Skip to content

Commit 8044f24

Browse files
committed
v1.0.14
1 parent c61eddb commit 8044f24

8 files changed

Lines changed: 530 additions & 267 deletions

File tree

source/alsa_volume.pas

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
unit alsa_volume;
2+
3+
{$mode objfpc}{$H+}
4+
5+
interface
6+
7+
uses
8+
Classes, SysUtils, ctypes, dynlibs;
9+
10+
function SetVolume(CardIndex: Integer; Percent: Integer): Boolean;
11+
function GetVolume(CardIndex: Integer; out Percent: Integer): Boolean;
12+
13+
implementation
14+
15+
type
16+
Psnd_mixer_t = Pointer;
17+
Psnd_mixer_elem_t = Pointer;
18+
Psnd_mixer_selem_id_t = Pointer;
19+
20+
var
21+
asound: TLibHandle;
22+
23+
snd_mixer_open: function(mixer: PPointer; mode: cint): cint; cdecl;
24+
snd_mixer_attach: function(mixer: Pointer; name: PChar): cint; cdecl;
25+
snd_mixer_selem_register: function(mixer: Pointer; options: Pointer; classp: PPointer): cint; cdecl;
26+
snd_mixer_load: function(mixer: Pointer): cint; cdecl;
27+
snd_mixer_first_elem: function(mixer: Pointer): Pointer; cdecl;
28+
snd_mixer_elem_next: function(elem: Pointer): Pointer; cdecl;
29+
snd_mixer_selem_is_active: function(elem: Pointer): cint; cdecl;
30+
snd_mixer_selem_get_name: function(elem: Pointer): PChar; cdecl;
31+
32+
snd_mixer_selem_has_playback_volume: function(elem: Pointer): cint; cdecl;
33+
snd_mixer_selem_get_playback_volume_range: function(elem: Pointer; min, max: Plongint): cint; cdecl;
34+
snd_mixer_selem_set_playback_volume_all: function(elem: Pointer; value: clong): cint; cdecl;
35+
snd_mixer_selem_get_playback_volume: function(elem: Pointer; channel: cint; value: Plongint): cint; cdecl;
36+
37+
snd_mixer_close: function(mixer: Pointer): cint; cdecl;
38+
39+
const
40+
SND_MIXER_SCHN_FRONT_LEFT = 0;
41+
42+
function LoadALSA: Boolean;
43+
begin
44+
if asound <> 0 then exit(True);
45+
46+
asound := LoadLibrary('libasound.so');
47+
if asound = 0 then exit(False);
48+
49+
Pointer(snd_mixer_open) := GetProcAddress(asound, 'snd_mixer_open');
50+
Pointer(snd_mixer_attach) := GetProcAddress(asound, 'snd_mixer_attach');
51+
Pointer(snd_mixer_selem_register) := GetProcAddress(asound, 'snd_mixer_selem_register');
52+
Pointer(snd_mixer_load) := GetProcAddress(asound, 'snd_mixer_load');
53+
Pointer(snd_mixer_first_elem) := GetProcAddress(asound, 'snd_mixer_first_elem');
54+
Pointer(snd_mixer_elem_next) := GetProcAddress(asound, 'snd_mixer_elem_next');
55+
Pointer(snd_mixer_selem_is_active) := GetProcAddress(asound, 'snd_mixer_selem_is_active');
56+
Pointer(snd_mixer_selem_get_name) := GetProcAddress(asound, 'snd_mixer_selem_get_name');
57+
58+
Pointer(snd_mixer_selem_has_playback_volume) := GetProcAddress(asound, 'snd_mixer_selem_has_playback_volume');
59+
Pointer(snd_mixer_selem_get_playback_volume_range) := GetProcAddress(asound, 'snd_mixer_selem_get_playback_volume_range');
60+
Pointer(snd_mixer_selem_set_playback_volume_all) := GetProcAddress(asound, 'snd_mixer_selem_set_playback_volume_all');
61+
Pointer(snd_mixer_selem_get_playback_volume) := GetProcAddress(asound, 'snd_mixer_selem_get_playback_volume');
62+
63+
Pointer(snd_mixer_close) := GetProcAddress(asound, 'snd_mixer_close');
64+
65+
Result := True;
66+
end;
67+
68+
function OpenMixer(CardIndex: Integer; out Mixer: Pointer): Boolean;
69+
var
70+
name: String;
71+
begin
72+
Result := False;
73+
74+
if snd_mixer_open(@Mixer, 0) < 0 then exit;
75+
76+
name := 'hw:' + IntToStr(CardIndex);
77+
78+
if snd_mixer_attach(Mixer, PChar(name)) < 0 then exit;
79+
if snd_mixer_selem_register(Mixer, nil, nil) < 0 then exit;
80+
if snd_mixer_load(Mixer) < 0 then exit;
81+
82+
Result := True;
83+
end;
84+
85+
function FindVolumeElem(Mixer: Pointer): Pointer;
86+
var
87+
elem: Pointer;
88+
begin
89+
Result := nil;
90+
91+
elem := snd_mixer_first_elem(Mixer);
92+
while elem <> nil do
93+
begin
94+
if (snd_mixer_selem_is_active(elem) <> 0) and
95+
(snd_mixer_selem_has_playback_volume(elem) <> 0) then
96+
begin
97+
Result := elem;
98+
exit;
99+
end;
100+
101+
elem := snd_mixer_elem_next(elem);
102+
end;
103+
end;
104+
105+
function SetVolume(CardIndex: Integer; Percent: Integer): Boolean;
106+
var
107+
mixer, elem: Pointer;
108+
minv, maxv: clong;
109+
value: clong;
110+
begin
111+
Result := False;
112+
113+
if not LoadALSA then exit;
114+
if not OpenMixer(CardIndex, mixer) then exit;
115+
116+
elem := FindVolumeElem(mixer);
117+
if elem = nil then
118+
begin
119+
snd_mixer_close(mixer);
120+
exit;
121+
end;
122+
123+
snd_mixer_selem_get_playback_volume_range(elem, @minv, @maxv);
124+
125+
value := minv + (Percent * (maxv - minv) div 100);
126+
127+
snd_mixer_selem_set_playback_volume_all(elem, value);
128+
129+
snd_mixer_close(mixer);
130+
Result := True;
131+
end;
132+
133+
function GetVolume(CardIndex: Integer; out Percent: Integer): Boolean;
134+
var
135+
mixer, elem: Pointer;
136+
minv, maxv, value: clong;
137+
begin
138+
Result := False;
139+
Percent := 0;
140+
141+
if not LoadALSA then exit;
142+
if not OpenMixer(CardIndex, mixer) then exit;
143+
144+
elem := FindVolumeElem(mixer);
145+
if elem = nil then
146+
begin
147+
snd_mixer_close(mixer);
148+
exit;
149+
end;
150+
151+
snd_mixer_selem_get_playback_volume_range(elem, @minv, @maxv);
152+
snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, @value);
153+
154+
if maxv > minv then
155+
Percent := (value - minv) * 100 div (maxv - minv);
156+
157+
snd_mixer_close(mixer);
158+
Result := True;
159+
end;
160+
161+
initialization
162+
asound := 0;
163+
164+
finalization
165+
if asound <> 0 then
166+
FreeLibrary(asound);
167+
168+
end.

source/udp_player

64.3 KB
Binary file not shown.

source/udp_player.ctpr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@
122122
<ResourceBaseClass Value="Form"/>
123123
<UnitName Value="Unit2"/>
124124
</Unit>
125+
<Unit>
126+
<Filename Value="alsa_volume.pas"/>
127+
<FRMtype Value="0"/>
128+
<IsPartOfProject Value="True"/>
129+
</Unit>
125130
</Units>
126131
</ProjectOptions>
127132
<CompilerOptions>

0 commit comments

Comments
 (0)