2015-05-01 90 views
2

背景相關聯如何將一個USB耳機麥克風和耳機/揚聲器

我需要顯示在軟電話應用連接耳機(組合麥克風和耳機)的列表。爲了測試我有以下設備:

  • 的Jabra PRO 9470
  • 繽特力BT300M
  • 羅技G430遊戲耳機

用戶應該能夠從ComboBox選擇耳機,而不選擇麥克風和耳機分開。

信息

我知道在哪裏可以找到有關的麥克風和耳機的信息(在Windows中),但我一直無法使用WMIMMDevice API得到它。

要找到信息,請右鍵單擊任務欄右側的Sound(揚聲器圖標),然後選擇Playback devices

Headset properties

  1. 打開屬性通過雙擊窗口或點擊Properties
  2. 單擊屬性窗口上的Properties按鈕。
  3. 單擊Details選項卡,然後在ComboBox中查找Children屬性。

這會給我提供以下信息:

SWD\MMDEVAPI\{0.0.0.00000000}.{f2e09e37-8389-46c4-8b2b-53e08b874399} 
SWD\MMDEVAPI\{0.0.1.00000000}.{3402ee6e-d862-47ca-8ab8-bb8254216032} 

第一行符合我Headset Earphone (Jabra PRO 9470)和第二Headset Microphone (Jabra PRO 9470)

要在C#中獲得相同的信息,我需要遍歷Win32_USBControllerDevice類並輸出包含「MMDEVAPI」的所有值。在我的電腦上,它會返回6個值(3個麥克風,3個耳機)。

foreach (var device in new ManagementObjectSearcher("SELECT * FROM Win32_USBControllerDevice").Get()) 
{ 
    foreach (var property in device.Properties) 
    { 
     // Gets the value of the property on the device. 
     var value = property.Value == null ? string.Empty : property.Value.ToString(); 

     if (value.IndexOf("mmdevapi", StringComparison.OrdinalIgnoreCase) > -1) 
     { 
      // Output connected USB microphones and earphones. 
      Console.WriteLine(property.Value); 
     } 
    } 
} 

僅供參考,上面的代碼將輸出:

\\PC9018\root\cimv2:Win32_PnPEntity.DeviceID="SWD\\MMDEVAPI\\{0.0.0.00000000}.{F2E09E37-8389-46C4-8B2B-53E08B874399}" 
\\PC9018\root\cimv2:Win32_PnPEntity.DeviceID="SWD\\MMDEVAPI\\{0.0.1.00000000}.{3402EE6E-D862-47CA-8AB8-BB8254216032}" 
\\PC9018\root\cimv2:Win32_PnPEntity.DeviceID="SWD\\MMDEVAPI\\{0.0.0.00000000}.{985F2B5C-2EE2-4733-BBD6-48BFDE2D5582}" 
\\PC9018\root\cimv2:Win32_PnPEntity.DeviceID="SWD\\MMDEVAPI\\{0.0.1.00000000}.{71D824EA-DAE9-4F0D-B673-4425385E3777}" 
\\PC9018\root\cimv2:Win32_PnPEntity.DeviceID="SWD\\MMDEVAPI\\{0.0.0.00000000}.{D29C0970-D515-4F91-9924-F0063CF1A196}" 
\\PC9018\root\cimv2:Win32_PnPEntity.DeviceID="SWD\\MMDEVAPI\\{0.0.1.00000000}.{C4B331E2-C56B-4D9B-A486-2ED6C11FDB8C}" 

問題

我現在最大的問題是,我該如何正確的耳機麥克風和耳機成Headset關聯目的?

的嘗試

我試圖尋找谷歌和StackOverflow的答案或提示,但我無法找到使用WMIMMDevice API麥克風和耳機之間的共同點或關係。

如果創建一個Dictionary<string, List<string>>其中Key是一些獨特的物理設備或USB接口的方式,並且Value是相關Win32_PnPEntity.DeviceID的列表,然後我找不到它。

星球大戰幾天精神日「 幫助我,StackOverflow上你是我唯一的希望

回答

3

它看起來像我已經找到自己的答案,藉助NAudio和Windows註冊表。問題中的代碼仍然正確,但NAudio使它更容易一些。

我發現Windows註冊表裏面的關鍵,我的問題下:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render 

每個設備都有一個稱爲{b3f8fa53-0004-438e-9003-51a46e139bfc},2與此類似{1}.USB\VID_047F&PID_0416&MI_00\7&21995D75&0&0000值屬性。

這看起來是一個獨特的硬件ID,並由耳機麥克風和耳機共享(與問題中的Children屬性相同)。

溶液

與單個方法來定位和返回耳機的列表的接口。

public interface IHeadsetLocator 
{ 
    /// <summary> 
    /// Locate all connected audio devices based on the given state. 
    /// </summary> 
    /// <param name="deviceState"></param> 
    /// <returns></returns> 
    IReadOnlyCollection<Headset> LocateConnectedAudioDevices(DeviceState deviceState = DeviceState.Active); 
} 

並完成實現。真正的奇蹟發生在GetHardwareToken方法的幫助下。

public class HeadsetLocator : IHeadsetLocator 
{ 
    /// <summary> 
    /// Locate all connected audio devices based on the given state. 
    /// </summary> 
    /// <param name="deviceState"></param> 
    /// <returns></returns> 
    public IReadOnlyCollection<Headset> LocateConnectedAudioDevices(DeviceState deviceState = DeviceState.Active) 
    { 
     var enumerator = new MMDeviceEnumerator(); 
     var relatedAudioDevices = new ConcurrentDictionary<string, List<MMDevice>>(); 
     var headsets = new List<Headset>(); 

     // Locate all connected audio devices. 
     foreach (var device in enumerator.EnumerateAudioEndPoints(DataFlow.All, deviceState)) 
     { 
      // Gets the DataFlow and DeviceID from the connected audio device. 
      var index = device.ID.LastIndexOf('.'); 
      var dataFlow = device.ID.Substring(0, index).Contains("0.0.0") ? DataFlow.Render : DataFlow.Capture; 
      var deviceId = device.ID.Substring(index + 1); 

      // Gets the unique hardware token. 
      var hardwareToken = GetHardwareToken(dataFlow, deviceId); 

      var audioDevice = relatedAudioDevices.GetOrAdd(hardwareToken, o => new List<MMDevice>()); 
      audioDevice.Add(device); 
     } 

     // Combines the related devices into a headset object. 
     foreach (var devicePair in relatedAudioDevices) 
     { 
      var capture = devicePair.Value.FirstOrDefault(o => o.ID.Contains("0.0.1")); 
      var render = devicePair.Value.FirstOrDefault(o => o.ID.Contains("0.0.0")); 

      if (capture != null && render != null) 
      { 
       headsets.Add(new Headset("Headset", render.DeviceFriendlyName, capture, render)); 
      } 
     } 

     return new ReadOnlyCollection<Headset>(headsets); 
    } 

    /// <summary> 
    /// Gets the token of the USB device. 
    /// </summary> 
    /// <param name="dataFlow"></param> 
    /// <param name="audioDeviceId"></param> 
    /// <returns></returns> 
    public string GetHardwareToken(DataFlow dataFlow, string audioDeviceId) 
    { 
     using (var registryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) 
     { 
      var captureKey = registryKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\" + dataFlow + @"\" + audioDeviceId + @"\Properties"); 
      if (captureKey != null) 
      { 
       return captureKey.GetValue("{b3f8fa53-0004-438e-9003-51a46e139bfc},2") as string; 
      } 
     } 

     return null; 
    } 
} 

我希望這可以幫助其他人在類似的情況。

快樂編碼

相關問題