繁体   English   中英

将主音频音量的变化确定为事件(音量变化侦听器)

[英]Determine changes of master audio volume as an event (volume change listener)

我想将Windows的主音量绑定到程序中的滑块。 因此,我进行了搜索,找到了一些GETSET主卷的方法以及类似以下的库:


编辑:

现在我有以下课程。 我创建它的一个实例,并使用propertchange事件通过Trace.WriteLine显示体积。 但是,当我更改Windows音量时,会导致无法处理的错误!

public class AudioEndpointVolumeEnforcer : INotifyPropertyChanged
{
    private MMDeviceEnumerator mmDeviceEnumerator;
    private MMDevice mmDevice;
    private AudioEndpointVolume audioEndpointVolume;
    private bool _deviceIsMuted;
    private int _desiredVolume;
    private int _volumePercent;

    public AudioEndpointVolumeEnforcer()
    {
        try
        {
            mmDeviceEnumerator = new MMDeviceEnumerator();
            mmDevice = mmDeviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
            audioEndpointVolume = mmDevice.AudioEndpointVolume;
            audioEndpointVolume.OnVolumeNotification += data =>
            {
                VolumePercent = Convert.ToInt16(data.MasterVolume*100);
                _deviceIsMuted = data.Muted;
            };
            DesiredVolume = 65;
        }
        catch (Exception ex)
        {
            // Logging logic here
        }
    }

    public int DesiredVolume
    {
        get { return _desiredVolume; }
        private set
        {
            if (_desiredVolume == value) return;
            _desiredVolume = value;

            //NotifyOfPropertyChange();
            OnPropertyChanged("DesiredVolume");

            Enforce(_desiredVolume);
        }
    }


    public int VolumePercent
    {
        get { return _volumePercent; }
        private set
        {
            if (_volumePercent == value) return;
            _volumePercent = value;
            if (_volumePercent != _desiredVolume)
            {
                _volumePercent = _desiredVolume;
                Enforce(_volumePercent);
            }
        }
    }

    public void Enforce(int pct, bool mute = false)
    {
        var adjusted = Convert.ToInt16(audioEndpointVolume.MasterVolumeLevelScalar*100);
        if (adjusted != DesiredVolume)
        {
            audioEndpointVolume.MasterVolumeLevelScalar = pct/100f;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

使用类:

 // Inside my window cunstractor >>
 audioVolume = new AudioEndpointVolumeEnforcer();
 audioVolume.PropertyChanged += MasterAudioVolumeChanged;


 private void MasterAudioVolumeChanged(object obj, PropertyChangedEventArgs eventArgs)
 {
   Trace.WriteLine(eventArgs.PropertyName+" - "+audioVolume.DesiredVolume);
 }

运行时错误:

...................................... 在此处输入图片说明

“输出”面板显示Access violation错误:

The program '[18488] Audio.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'

编辑

我通过断点和跟踪测试了上面的代码。 上述错误有时在波纹管部分中发生:

audioEndpointVolume.OnVolumeNotification += data =>
{
    VolumePercent = Convert.ToInt16(data.MasterVolume*100);
    _deviceIsMuted = data.Muted;
};

例如, 有时会在以下行中发生:

_deviceIsMuted = data.Muted;

但是当我按F11转到下一步时, 它在程序内部未显示正常错误! 它导致波纹管错误窗口和作用力关闭!

............................................... 在此处输入图片说明

Access violation

您可以这样使用NAudio库:

using NAudio;
using NAudio.CoreAudioApi;

private static MMDeviceEnumerator enumer = new MMDeviceEnumerator();
private MMDevice dev = enumer.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);

public void Form1_Load(object sender, EventArgs e){
    dev.AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification;
}

void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
{
    // This shows data.MasterVolume, you can do whatever you want here
    MessageBox.Show(data.MasterVolume.ToString());
}

本示例使用WinForms项目,但您也可以在其他位置创建事件。

NAudio可以作为NuGet软件包安装,也可以从https://naudio.codeplex.com/安装。

音量范围从0.0f到1.0f,只需执行以下操作即可获得0-100:

(int)(data.MasterVolume * 100f)

您的代码是否根据事件更新控件,例如轨迹栏或静音按钮? 如果是这样,您可能需要使用线程安全的方法。 控件只能由UI线程更新。 Me.InvokeRequired检查是否是要执行更新的是UI线程。 如果不是,则返回True。 然后Me.Invoke使用委托来处理两个线程之间的通信。 如果您不使用Me.Invoke,则会发生访问冲突。

Delegate Sub UpdateCallback(Volume As Integer, Muted As Boolean)
Public Overloads Sub Update(Volume As Integer, Muted As Boolean)
    If tbVolume.InvokeRequired Then
        Dim d As New UpdateCallback(AddressOf Update)
        Me.Invoke(d, Volume, Muted)
    Else
        tbVolume.Value = Volume
        _Mute = Muted
        btnMuteUnmute.BackgroundImage = DirectCast(If(_Mute, _
           My.Resources.mute, My.Resources.Unmute), Icon).ToBitmap
    End If
End Sub

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM