我正在使用 NAudio 完成一些任务:
- 找到“立体声混音”源行
- 通过启用任何存在的线路控制来取消“立体声混音”源线路的静音
- 通过禁用存在的任何线路控件,使同一输入设备上的所有其他源线路静音
我编写的程序可以正常执行任务 1,但任务 2 和 3 失败。
具体来说,这段代码会导致 ArgumentException 被抛出:
if( control.IsBoolean ) {
BooleanMixerControl boolControl = (BooleanMixerControl)control;
boolControl.Value = isMuted;
set = true;
if( boolControl.Value != isMuted )
throw new ArgumentException("Could not set line muted value.");
}
这是我用来执行这些任务的静态类。它依赖于当前版本的 NAudio:
public static class RecordSourceManager {
public static Boolean GetMicrophoneMuted(String deviceName) {
Mixer mixer = GetMixer( deviceName );
if( mixer == null ) throw new ArgumentException("Specified device \"" + deviceName + "\" does not exist.");
foreach(MixerLine line in mixer.Destinations) {
foreach(MixerLine sourceLine in line.Sources) {
if( sourceLine.ComponentType == MixerLineComponentType.SourceMicrophone ) {
return GetLineMuted( sourceLine );
}
}
}
throw new ArgumentException("Specified device \"" + deviceName + "\" does not contain a microphone device.");
}
public static void SetMicrophoneExclusive(String deviceName, Boolean enableMicrophoneExclusivity) {
Mixer mixer = GetMixer( deviceName );
if( mixer == null ) throw new ArgumentException("Specified device \"" + deviceName + "\" does not exist.");
foreach(MixerLine line in mixer.Destinations) {
foreach(MixerLine sourceLine in line.Sources) {
if( sourceLine.ComponentType == MixerLineComponentType.SourceMicrophone ) {
SetLineMuted( sourceLine, !enableMicrophoneExclusivity );
} else {
SetLineMuted( sourceLine, enableMicrophoneExclusivity );
}
}
}
}
public static Boolean GetStereoMixMuted(String deviceName) {
Mixer mixer = GetMixer( deviceName );
if( mixer == null ) throw new ArgumentException("Specified device \"" + deviceName + "\" does not exist.");
foreach(MixerLine line in mixer.Destinations) {
foreach(MixerLine sourceLine in line.Sources) {
if( IsStereoMix( sourceLine.Name ) ) {
return GetLineMuted( sourceLine );
}
}
}
throw new ArgumentException("Specified device \"" + deviceName + "\" does not contain a microphone device.");
}
public static void SetStereoMixExclusive(String deviceName, Boolean enableStereoMixExclusivity) {
Mixer mixer = GetMixer( deviceName );
if( mixer == null ) throw new ArgumentException("Specified device \"" + deviceName + "\" does not exist.");
MixerLine stereoMix;
MixerLine parentLine;
GetStereoMixLine( mixer, out stereoMix, out parentLine );
if( stereoMix == null ) throw new ArgumentException("Specified device \"" + deviceName + "\" does not contain a Stereo Mix line.");
foreach(MixerLine source in parentLine.Sources) {
Boolean ok;
if( IsStereoMix( source.Name ) ) {
ok = SetLineMuted( source, !enableStereoMixExclusivity );
} else {
ok = SetLineMuted( source, enableStereoMixExclusivity );
}
if( !ok ) throw new ArgumentException("Could not set line muted state.");
}
}
private static Mixer GetMixer(String deviceName) {
foreach(Mixer mixer in Mixer.Mixers) {
//wtr.WriteLine("Mixer: {0}, Mfg: {1}", mixer.Name, mixer.Manufacturer );
if( String.Equals( mixer.Name, deviceName, StringComparison.OrdinalIgnoreCase ) ) return mixer;
}
return null;
}
private static void GetStereoMixLine(Mixer device, out MixerLine stereoMix, out MixerLine parentLine) {
foreach(MixerLine line in device.Destinations) {
foreach(MixerLine source in line.Sources) {
if( IsStereoMix( source.Name ) ) {
stereoMix = source;
parentLine = line;
return;
}
}
}
stereoMix = null;
parentLine = null;
}
private static Boolean IsStereoMix(String sourceName) {
String[] names = new String[] {
"Stereo Mix",
"What U Hear",
"What \"U\" Hear",
"What-U-Hear",
"Playback Redirect",
"Wave Out",
"Wave Out Mix",
"Wave-Out Mix"
};
foreach(String name in names) {
if( String.Equals( sourceName, name, StringComparison.OrdinalIgnoreCase ) ) return true;
}
return false;
}
private static Boolean SetLineMuted(MixerLine line, Boolean isMuted) {
Boolean set = false;
foreach(MixerControl control in line.Controls) {
// Can't test if control's name == "Mute" because sometimes it's "Mic Volume" (even though it's boolean). Same goes for GetLineMuted.
if( control.IsBoolean ) {
BooleanMixerControl boolControl = (BooleanMixerControl)control;
boolControl.Value = isMuted;
set = true;
if( boolControl.Value != isMuted )
throw new ArgumentException("Could not set line muted value.");
}
}
return set;
}
private static Boolean GetLineMuted(MixerLine line) {
foreach(MixerControl control in line.Controls) {
if( control.IsBoolean ) {
BooleanMixerControl boolControl = (BooleanMixerControl)control;
return boolControl.Value;
}
}
return false;
}
}
我想我会看看 NAudio 的 BooleanMixerControl 类,我看到了这个:
public bool Value {
get {
base.GetControlDetails();
return (this.boolDetails.fValue == 1);
}
set {
MmException.Try(MixerInterop.mixerSetControlDetails(base.mixerHandle, ref this.mixerControlDetails, base.mixerHandleType), "mixerSetControlDetails");
}
}
有趣的是,属性设置器的参数似乎value
被忽略了,因此,mixerSetControlDetails 调用不会做任何有用的工作。这是 NAudio 中的错误吗?