📄 unamsmixer.pas
字号:
result := getLineIndex(not isOut, 1);
//
if (0 < result) then
result := 0
else
if (0 = result) then begin
//
result := min(1, getLineCount() - 1);
if (0 = result) then
result := -1; // no such line
end
else
if (isOut) then begin
//
if (0 < getLineCount()) then
result := 0 // finally assume 0 is OUT
else
result := -1
end
else begin
//
if (0 < getLineCount()) then
result := 1 // finally assume 1 is IN
else
result := -1
end;
end
else
result := f_selectedMixer.f_lines.locate(line);
end;
end;
// -- --
function unaMsMixerSystem.getLineName(iline: unsigned; shortName: bool): wideString;
begin
if ((nil <> f_selectedMixer) and (nil <> f_selectedMixer.line[iline])) then begin
//
if (shortName) then
result := f_selectedMixer.line[iline].caps.szShortName
else
result := f_selectedMixer.line[iline].caps.szName
end
else
result := '';
end;
// -- --
function unaMsMixerSystem.getMixer(index: unsigned): unaMsMixerDevice;
begin
result := f_mixers[index];
end;
// -- --
function unaMsMixerSystem.getMixerCount(): unsigned;
begin
result := f_mixers.count;
end;
const
// message base for driver specific messages.
//
DRVM_MAPPER = $2000;
DRVM_USER = $4000;
DRVM_MAPPER_STATUS = (DRVM_MAPPER+0);
DRVM_MAPPER_RECONFIGURE = (DRVM_MAPPER+1);
DRVM_MAPPER_PREFERRED_GET = (DRVM_MAPPER+21);
DRV_QUERYMODULE = (DRV_RESERVED + 9);
DRV_PNPINSTALL = (DRV_RESERVED + 11);
// MS loves to hide things
DRV_QUERYDRVENTRY = (DRV_RESERVED + 1);
DRV_QUERYDEVNODE = (DRV_RESERVED + 2);
DRV_QUERYNAME = (DRV_RESERVED + 3);
DRV_QUERYDRIVERIDS = (DRV_RESERVED + 4);
DRV_QUERYMAPPABLE = (DRV_RESERVED + 5);
//
// DRVM_MAPPER_PREFERRED_GET flags
//
DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY = $000000001;
// -- --
function unaMsMixerSystem.getMixerId(deviceId: unsigned; isInDevice: bool): int;
var
mixId: unsigned;
flags: unsigned;
begin
if (WAVE_MAPPER = deviceId) then begin
//
flags := 0; //
case (g_osVersion.dwPlatformId) of
VER_PLATFORM_WIN32s,
VER_PLATFORM_WIN32_WINDOWS: begin
// Win95/Me stuff
deviceId := mapMixerIdWin9x(deviceId, isInDevice);
end;
VER_PLATFORM_WIN32_NT: begin
// NT stuff
if (isInDevice) then
waveInMessage(int(WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, unsigned(@deviceId), unsigned(@flags))
else
waveOutMessage(int(WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, unsigned(@deviceId), unsigned(@flags));
end;
end;
end;
//
if (MMSYSERR_NOERROR = mixerGetID(int(deviceId), mixId, choice(isInDevice, MIXER_OBJECTF_WAVEIN, unsigned(MIXER_OBJECTF_WAVEOUT)))) then
result := mixId
else
result := -1;
end;
// -- --
function unaMsMixerSystem.getMixerIndex(mixerId: unsigned): int;
var
i: unsigned;
curId: unsigned;
begin
result := -1;
// locate mixer with this ID
i := 0;
while (i < getMixerCount()) do begin
//
if (MMSYSERR_NOERROR = mixerGetID(i, curId, MIXER_OBJECTF_MIXER)) then
//
if (curId = mixerId) then begin
//
result := i;
break;
end;
//
inc(i);
end;
end;
// -- --
function unaMsMixerSystem.getMixerName(): wideString;
begin
if (nil <> f_selectedMixer) then
result := f_selectedMixer.caps.szPname
else
result := '';
end;
// -- --
function unaMsMixerSystem.getMuteControlID(iline: unsigned; iconn: int): int;
var
control: unaMsMixerControl;
begin
control := getConnectionControl(iline, iconn, MIXERCONTROL_CT_CLASS_SWITCH, MIXERCONTROL_CONTROLTYPE_MUTE);
//
if (nil <> control) then
result := control.caps.dwControlID
else
result := -1;
end;
// -- --
function unaMsMixerSystem.getRecSource(): int;
var
i: unsigned;
j: unsigned;
k: unsigned;
recIndex: int;
line: unaMsMixerLine;
conn: unaMsMixerLine;
control: unaMsMixerControl;
begin
result := -1;
//
if (nil <> f_selectedMixer) then begin
//
recIndex := getLineIndex(false);
if (0 <= recIndex) then
line := f_selectedMixer.line[recIndex]
else
line := nil;
//
if (nil <> line) then begin
//
//
// locate list control(s) for this line
//
i := 0;
while (i < line.getControlCount()) do begin
//
control := line[i];
if (control.isListClass) then begin
// locate this line in items list
j := 0;
while (j < control.caps.cMultipleItems) do begin
//
if (control.getValue(false, 0, j)) then begin
//
// now locate this line in connections
//
k := 0;
while (k < line.getConnectionCount) do begin
//
conn := line.connections[k];
if (conn.caps.dwLineId = control.getListItem(0, j).dwParam1) then begin
// found
result := k;
break;
end;
//
inc(k);
end;
//
if (0 <= result) then
break;
end;
//
inc(j);
end;
end;
//
if (0 <= result) then
break;
//
inc(i);
end;
end;
end;
end;
// -- --
function unaMsMixerSystem.getVolume(iline: unsigned; iconn: int): int;
var
control: unaMsMixerControl;
imax: int;
begin
control := getConnectionControl(iline, iconn, MIXERCONTROL_CT_CLASS_FADER, MIXERCONTROL_CONTROLTYPE_VOLUME);
//
if (nil <> control) then begin
//
imax := max(control.caps.bounds.lMinimum, control.caps.bounds.lMaximum) - control.caps.bounds.lMinimum;
//
result := (control.getValue(unsigned(0), 0) + control.getValue(unsigned(0), 1)) shr 1;
result := percent(result, imax);
end
else
result := -1;
end;
// -- --
function unaMsMixerSystem.getVolumeControlID(iline: unsigned; iconn: int): int;
var
control: unaMsMixerControl;
begin
control := getConnectionControl(iline, iconn, MIXERCONTROL_CT_CLASS_FADER, MIXERCONTROL_CONTROLTYPE_VOLUME);
//
if (nil <> control) then
result := control.caps.dwControlID
else
result := -1;
end;
// -- --
function unaMsMixerSystem.isMutedConnection(iline: unsigned; iconn: int): bool;
var
control: unaMsMixerControl;
begin
control := getConnectionControl(iline, iconn, MIXERCONTROL_CT_CLASS_SWITCH, MIXERCONTROL_CONTROLTYPE_MUTE);
//
if (nil <> control) then
result := control.getValue(true)
else
result := true;
end;
// -- --
function unaMsMixerSystem.mapMixerIdWin9x(deviceId: unsigned; isInDevice: bool): unsigned;
var
key: HKEY;
buf: array[0..512] of char;
lpType: DWORD;
lpSize: DWORD;
devCapsIn: WAVEINCAPSA;
devCapsOut: WAVEOUTCAPSA;
count: unsigned;
i: unsigned;
name: string;
ok: bool;
begin
result := deviceId;
if (WAVE_MAPPER <> result) then
exit;
//
// 1. first try to read mapped device name from registry
if (ERROR_SUCCESS = regOpenKeyEx(HKEY_CURRENT_USER, 'Software\Microsoft\Multimedia\Sound Mapper', 0, KEY_READ, key)) then try
lpType := REG_SZ;
lpSize := sizeof(buf);
RegQueryValueEx(key, pChar(choice(isInDevice, 'Record', 'Playback')), nil, @lpType, @buf, @lpSize);
finally
regCloseKey(key);
end;
// 2. now, for all devices, try to compare the name (say thanks to MS)
if (isInDevice) then
count := waveInGetNumDevs()
else
count := waveOutGetNumDevs();
//
i := 0;
while (i < count) do begin
//
name := '';
if (isInDevice) then begin
if (MMSYSERR_NOERROR = waveInGetDevCapsA(i, @devCapsIn, sizeof(devCapsIn))) then
name := devCapsIn.szPname;
end
else begin
if (MMSYSERR_NOERROR = waveOutGetDevCapsA(i, @devCapsOut, sizeof(devCapsOut))) then
name := devCapsOut.szPname;
end;
//
if (sameString(name, buf)) then begin
result := i;
break;
end;
//
inc(i);
end;
// 3. if still no success, try DRV_QUERYMAPPABLE
if (WAVE_MAPPER = result) then begin
//
i := 0;
while (i < count) do begin
//
if (isInDevice) then
ok := (MMSYSERR_NOERROR = waveInMessage(i, DRV_QUERYMAPPABLE, 0, 0))
else
ok := (MMSYSERR_NOERROR = waveOutMessage(i, DRV_QUERYMAPPABLE, 0, 0));
//
if (ok) then begin
result := i;
break;
end;
//
inc(i);
end;
end;
end;
// -- --
function unaMsMixerSystem.muteConnection(iline: unsigned; iconn: int; doMute: bool): bool;
var
control: unaMsMixerControl;
begin
control := getConnectionControl(iline, iconn, MIXERCONTROL_CT_CLASS_SWITCH, MIXERCONTROL_CONTROLTYPE_MUTE);
//
if (nil <> control) then begin
//
control.setValue(doMute);
result := true;
end
else
result := false;
end;
// -- --
function unaMsMixerSystem.selectMixer(imixer: unsigned; handle: unsigned): bool;
begin
if (nil <> f_selectedMixer) then
f_selectedMixer.close();
//
f_selectedMixer := nil;
//
if (imixer < getMixerCount()) then
f_selectedMixer := mixer[imixer];
//
result := (nil <> f_selectedMixer);
//
if (result) then begin
//
f_selectedMixer.winHandle := handle;
f_selectedMixer.open();
end;
end;
// -- --
function unaMsMixerSystem.selectMixer(deviceId: unsigned; isInDevice: bool; handle: unsigned): bool;
var
mixId: int;
i: int;
begin
mixId := getMixerId(deviceId, isInDevice);
//
if (0 <= mixId) then
// locate mixer with this ID
i := getMixerIndex(mixId)
else
i := -1; // no mixer for this device
//
if (0 <= i) then
result := selectMixer(i, handle)
else
result := selectMixer($FFFFFFFF, handle) // select nil
end;
// -- --
function unaMsMixerSystem.setRecSource(iconn: unsigned; ensureNotMuted: bool): bool;
var
i: unsigned;
j: unsigned;
recIndex: int;
line: unaMsMixerLine;
conn: unaMsMixerLine;
control: unaMsMixerControl;
begin
result := false;
//
if (nil <> f_selectedMixer) then begin
//
recIndex := getLineIndex(false);
if (0 <= recIndex) then
line := f_selectedMixer.line[recIndex]
else
line := nil;
//
if (nil <> line) then begin
//
conn := line.connections[iconn];
if (nil <> conn) then begin
//
// locate list control(s) for this line
//
i := 0;
while (i < line.getControlCount()) do begin
//
control := line[i];
if (control.isListClass) then begin
// locate this line in items list
j := 0;
while (j < control.caps.cMultipleItems) do begin
//
if (control.getListItem(0, j).dwParam1 = conn.caps.dwLineId) then begin
control.setValue(true, 0, j);
result := true;
break;
end;
//
inc(j);
end;
//
if (result) then
break;
end;
//
inc(i);
end;
//
if (not result and ensureNotMuted) then
// at least make sure this line is not muted
muteConnection(recIndex, iconn, false);
end;
end;
end;
end;
// -- --
function unaMsMixerSystem.setVolume(iline: unsigned; iconn, value: int): bool;
var
control: unaMsMixerControl;
imax: int;
ivalue: int;
begin
control := getConnectionControl(iline, iconn, MIXERCONTROL_CT_CLASS_FADER, MIXERCONTROL_CONTROLTYPE_VOLUME);
if (nil <> control) then begin
//
imax := max(control.caps.bounds.lMinimum, control.caps.bounds.lMaximum) - control.caps.bounds.lMinimum;
ivalue := (imax div 100) * value + control.caps.bounds.lMinimum;
//
control.setValueInt(ivalue, 0);
control.setValueInt(ivalue, 1);
//
result := true;
end
else
result := false;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -