猿问

为什么 IAudioEndpointVolume::SetMute 不适用于 C# Interop?

我正在尝试IAudioEndpointVolume::SetMute使用 Interop 从 C#调用 Windows Core Audio 。


使用 C++ 实现,它工作正常。但是当我尝试从 C# 应用程序执行相同的调用时,没有任何变化。C# 应用程序的奇怪之处在于,如果我调用SetMute什么都不会发生,但是如果我调用SetMasterVolumeLevelScalar,它会有效地改变音量。


我的实现是这样的:


using System;

using System.Runtime.InteropServices;


namespace App

{

    [ComImport]

    [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

    interface IMMDeviceEnumerator

    {

        void _VtblGap1_1();

        int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice ppDevice);

    }


    [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

    interface IMMDevice

    {

        int Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);

        int OpenPropertyStore([MarshalAs(UnmanagedType.U4)] UInt32 accessMode, [MarshalAs(UnmanagedType.Interface)] out object properties);

        int GetId([MarshalAs(UnmanagedType.LPWStr)] out string strId);

    }



Interop 实现有什么问题吗?


慕丝7291255
浏览 280回答 1
1回答

慕村9548890

我努力尝试并最终成功,这些“_VtblGaps_”是关键......只需将所有内容复制粘贴到一个新的 C# 脚本中并从您的程序脚本中使用:using System;using System.Runtime.InteropServices;using System.Windows.Forms;namespace MMDeviceAPI{public class MMDeviceController{    [ComImport]    [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]    private class MMDeviceEnumerator    {    }    [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IMMDeviceEnumerator    {        void _VtblGap1_1();        //void _VtblGap1_5(); /// (Alternative)        [PreserveSig]        int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);    }    [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IMMDevice    {        [PreserveSig]        int Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);        void _VtblGap1_1();        int GetId([MarshalAs(UnmanagedType.LPWStr)] out string strId);    }    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IAudioEndpointVolume    {    }    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IGetChannelCount : IAudioEndpointVolume    {        void _VtblGap1_2();        int GetChannelCount(ref uint pnChannelCount);    }    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IGetChannelVolumeLevelScalar : IAudioEndpointVolume    {        void _VtblGap1_10();        int GetChannelVolumeLevelScalar(uint nChannel, ref float pfLevel);    }    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IGetMasterVolumeLevelScalar : IAudioEndpointVolume    {        void _VtblGap1_6();        int GetMasterVolumeLevelScalar(ref float pfLevel);    }    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IGetMute : IAudioEndpointVolume    {        void _VtblGap1_12();        int GetMute([MarshalAs(UnmanagedType.Bool)] ref bool pbMute);    }    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface ISetChannelVolumeLevelScalar : IAudioEndpointVolume    {        void _VtblGap1_8();        int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, [MarshalAs(UnmanagedType.LPStruct)] Guid pguidEventContext);    }    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface ISetMasterVolumeLevelScalar : IAudioEndpointVolume    {        void _VtblGap1_4();        int SetMasterVolumeLevelScalar(float fLevel, [MarshalAs(UnmanagedType.LPStruct)] Guid pguidEventContext);    }    [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface ISetMute : IAudioEndpointVolume    {        void _VtblGap1_11();        int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, [MarshalAs(UnmanagedType.LPStruct)] Guid pguidEventContext);    }    public enum EDataFlow { eRender, eCapture, eAll };    public enum ERole { eConsole, eMultimedia, eCommunications };    ///====================================================================================================    private static IAudioEndpointVolume GetMMDeviceAudioEndpointVolume(EDataFlow dataFlow, ERole role)    {        IMMDeviceEnumerator MMDeviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());        MMDeviceEnumerator.GetDefaultAudioEndpoint(dataFlow, role, out IMMDevice MMDevice);        MMDevice.Activate(typeof(IAudioEndpointVolume).GUID, 0, IntPtr.Zero, out object o);        IAudioEndpointVolume AudioEndpointVolume = (IAudioEndpointVolume)o;        Marshal.ReleaseComObject(MMDevice);        Marshal.ReleaseComObject(MMDeviceEnumerator);        return AudioEndpointVolume;    }    public static uint GetChannelCount(EDataFlow dataFlow, ERole role)    {        IGetChannelCount AudioEndpointVolume = (IGetChannelCount)GetMMDeviceAudioEndpointVolume(dataFlow, role);        uint returnValue = 0;        AudioEndpointVolume.GetChannelCount(ref returnValue);        Marshal.ReleaseComObject(AudioEndpointVolume);        return returnValue;    }    public static float GetChannelVolumeLevelScalar(EDataFlow dataFlow, ERole role, uint channel)    {        IGetChannelVolumeLevelScalar AudioEndpointVolume = (IGetChannelVolumeLevelScalar)GetMMDeviceAudioEndpointVolume(dataFlow, role);        float returnValue = 0;        AudioEndpointVolume.GetChannelVolumeLevelScalar(channel, ref returnValue);        Marshal.ReleaseComObject(AudioEndpointVolume);        return returnValue;    }    public static float GetMasterVolumeLevelScalar(EDataFlow dataFlow, ERole role)    {        IGetMasterVolumeLevelScalar AudioEndpointVolume = (IGetMasterVolumeLevelScalar)GetMMDeviceAudioEndpointVolume(dataFlow, role);        float returnValue = 0f;        AudioEndpointVolume.GetMasterVolumeLevelScalar(ref returnValue);        Marshal.ReleaseComObject(AudioEndpointVolume);        return returnValue;    }    public static bool GetMute(EDataFlow dataFlow, ERole role)    {        IGetMute AudioEndpointVolume = (IGetMute)GetMMDeviceAudioEndpointVolume(dataFlow, role);        bool returnValue = false;        AudioEndpointVolume.GetMute(ref returnValue);        Marshal.ReleaseComObject(AudioEndpointVolume);        return returnValue;    }    public static void SetChannelVolumeLevelScalar(EDataFlow dataFlow, ERole role, uint channel, float volume)    {        ISetChannelVolumeLevelScalar AudioEndpointVolume = (ISetChannelVolumeLevelScalar)GetMMDeviceAudioEndpointVolume(dataFlow, role);        AudioEndpointVolume.SetChannelVolumeLevelScalar(channel, volume, Guid.Empty);        Marshal.ReleaseComObject(AudioEndpointVolume);    }    public static void SetMasterVolumeLevelScalar(EDataFlow dataFlow, ERole role, float volume)    {        ISetMasterVolumeLevelScalar AudioEndpointVolume = (ISetMasterVolumeLevelScalar)GetMMDeviceAudioEndpointVolume(dataFlow, role);        AudioEndpointVolume.SetMasterVolumeLevelScalar(volume, Guid.Empty);        Marshal.ReleaseComObject(AudioEndpointVolume);    }    public static void SetMute(EDataFlow dataFlow, ERole role, bool mute)    {        ISetMute AudioEndpointVolume = (ISetMute)GetMMDeviceAudioEndpointVolume(dataFlow, role);        AudioEndpointVolume.SetMute(mute, Guid.Empty);        Marshal.ReleaseComObject(AudioEndpointVolume);    }    ///====================================================================================================    public static void TestFunctionality()    {        int device = 0;        EDataFlow dataFlow;        ERole eRole;        while (true)        {            device++;            switch (device)            {                case 1:                dataFlow = EDataFlow.eRender;                eRole = ERole.eMultimedia;                break;                case 2:                dataFlow = EDataFlow.eCapture;                eRole = ERole.eMultimedia;                break;                default:                return;            }            MessageBox.Show($"[EDataFlow & ERole]:  {dataFlow.ToString()}_{eRole.ToString()}");            uint channels = GetChannelCount(dataFlow, eRole); MessageBox.Show("[GetChannelCount]:  " + channels);            MessageBox.Show("[GetChannelVolumeLevelScalar #0]:  " + GetChannelVolumeLevelScalar(dataFlow, eRole, 0).ToString());            if (channels > 1) { MessageBox.Show("[GetChannelVolumeLevelScalar #1]:  " + GetChannelVolumeLevelScalar(dataFlow, eRole, 1).ToString()); }            MessageBox.Show("[GetMasterVolumeLevelScalar]:  " + GetMasterVolumeLevelScalar(dataFlow, eRole).ToString());            MessageBox.Show("[GetMute]:  " + GetMute(dataFlow, eRole).ToString());            MessageBox.Show("[SetChannelVolumeLevelScalar #0]:  0.44"); SetChannelVolumeLevelScalar(dataFlow, eRole, 0, 0.44f);            if (channels > 1) { MessageBox.Show("[SetChannelVolumeLevelScalar #1]:  0.88"); SetChannelVolumeLevelScalar(dataFlow, eRole, 1, 0.88f); }            MessageBox.Show("[SetMasterVolumeLevelScalar]:  0.55"); SetMasterVolumeLevelScalar(dataFlow, eRole, 0.55f);            MessageBox.Show("[SetMute]:  false"); SetMute(dataFlow, eRole, false);        }    }    ///====================================================================================================}}
随时随地看视频慕课网APP
我要回答