簡體   English   中英

獲取默認音頻/視頻設備

[英]Get default audio/video device

我正在使用 dotNet c#。 我需要確定默認的視頻和音頻設備我知道我可以枚舉音頻設備但如何確定默認設備? ManagementObjectSearcher mo = new ManagementObjectSearcher("select * from Win32_SoundDevice");

        foreach (ManagementObject soundDevice in mo.Get())
        {
            String deviceId = soundDevice.GetPropertyValue("DeviceId").ToString();
            String name = soundDevice.GetPropertyValue("Name").ToString();
            String status = soundDevice.GetPropertyValue("StatusInfo").ToString();

        }

聚會太晚了,但我最近在努力弄清楚如何在不依賴像NAudio這樣的 3rd 方項目的情況下獲取音頻設備信息。 注冊表似乎跟上音頻播放和錄制設備的變化。 這應該為您提供獲取已啟用或活動的音頻錄制或播放設備名稱的方法。 不能說它會永遠完美無缺,但它現在對我有用。 我是 C# 的新手,所以在閱讀評論時請記住這一點。

using Microsoft.Win32;
using System;

namespace RetrieveAudioDeviceInfo
{
    class Program
    {
        static void Main(string[] args)
        {
            string RequestedDeviceStatus = "Active"; // Initialize string variable for storing audio device status of interest. Valid input = "Active" or "Enabled"
            string RequestedDeviceType = "Playback"; // Initialize string variable for storing audio device type of interest. Valid input = "Playback" or "Recording"

            if (!String.Equals(RequestedDeviceStatus, "Active", StringComparison.OrdinalIgnoreCase) && !String.Equals(RequestedDeviceStatus, "Enabled", StringComparison.OrdinalIgnoreCase)) // Check RequestedDeviceStatus to ensure valid input was provided
            {
                Console.WriteLine("Invalid AudioDeviceStatus specified. Info request canceled"); // Output info to event log
                Console.ReadLine(); // Wait for user input
                return; // Immediately stop processing the inline function
            }
            string DeviceRegistryName; // Declare string variable for storing the registry name for the device type of interest

            if (String.Equals(RequestedDeviceType, "Playback", StringComparison.OrdinalIgnoreCase)) // Check if info request is for playback devices
                DeviceRegistryName = "Render"; // Set the DeviceRegistryName
            else if (String.Equals(RequestedDeviceType, "Recording", StringComparison.OrdinalIgnoreCase)) // Check if info request is for recording devices
                DeviceRegistryName = "Capture"; // Set the DeviceRegistryName
            else
            {
                Console.WriteLine("Invalid AudioDeviceType specified. Info request canceled"); // Output info to event log
                Console.ReadLine(); // Wait for user input
                return; // Immediately stop processing the inline function
            }
            RegistryKey RootKey; // Initialize RegistryKey for containing the root (base) key to evaluate

            if (Environment.Is64BitOperatingSystem) // Check if operating system is 64-bit
                RootKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); // Opens registry's LocalMachine key with a 64-bit view
            else
                RootKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); // Opens registry's LocalMachine key with a 32-bit view
            string AudioKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio"; // Parent registry key for audio devices
            string DeviceName, DeviceType; // Declare string variables for storing audio device information
            string[] ActiveDeviceRoles = null; // Initialize string array for storing information about the active devices for each audio role

            using (RegistryKey ChildKey = RootKey.OpenSubKey(AudioKey)) // Open subkey of AudioKey and store in ChildKey. "using" implemented for proper disposal.
            {
                foreach (string ChildKeyName in ChildKey.GetSubKeyNames()) // Loop through each SubKeyName in ChildKey
                {
                    if (ChildKeyName == DeviceRegistryName) // Check if ChildKeyName is "Render" (signifies registry folder for audio playback devices)
                    {
                        using (RegistryKey RenderKey = ChildKey.OpenSubKey(ChildKeyName)) // Open subkey of ChildKey and store in RenderKey. "using" implemented for proper disposal.
                        {
                            DateTime[] ActiveDeviceRoleTimes = null; // Initialize DateTime array for storing times when audio devices last held a particular audio role
                            int j = 1; // Initialize integer variable for tracking audio playback device count
                            foreach (string DeviceKeyName in RenderKey.GetSubKeyNames()) // Loop through each SubKeyName in RenderKey
                            {
                                using (RegistryKey DeviceKey = RenderKey.OpenSubKey(DeviceKeyName)) // Open subkey of RenderKey and store in DeviceKey. "using" implemented for proper disposal.
                                {
                                    if (Convert.ToInt32(DeviceKey.GetValue("DeviceState")) == 1) // Check if current audio device is enabled
                                    {
                                        string CurrentDeviceInfo; // Declare string variable for storing information about the current audio device
                                        using (RegistryKey DeviceKeyProperties = DeviceKey.OpenSubKey("Properties")) // Open "Properties" subkey of DeviceKey and store in DeviceKeyProperties. "using" implemented for proper disposal.
                                        {
                                            DeviceName = DeviceKeyProperties.GetValue("{b3f8fa53-0004-438e-9003-51a46e139bfc},6").ToString(); // Retrieve the current device's name from the registry
                                            DeviceType = DeviceKeyProperties.GetValue("{a45c254e-df1c-4efd-8020-67d146a850e0},2").ToString(); // Retrieve the current device's type from the registry
                                            CurrentDeviceInfo = DeviceType + " (" + DeviceName + ")"; // Combine the DeviceName and DeviceType info similar to how VoiceAttack displays this data in the Options menu
                                            if (String.Equals(RequestedDeviceStatus, "Enabled", StringComparison.OrdinalIgnoreCase)) // Check if user wants to show which audio devices are enabled
                                            {
                                                Console.WriteLine("Audio " + RequestedDeviceType + " Device " + j++ + " = " + CurrentDeviceInfo); // Output the CurrentDeviceInfo to the event log
                                                continue; // Continue with next index in parent for loop
                                            }
                                        }

                                        string[] roles = { "Role:0", "Role:1", "Role:2" }; // Initialize string array for storing the names of the different audio roles
                                        DateTime[] CurrentDeviceRoleTimes = new DateTime[roles.Length]; // Initialize DateTime array for storing times when the current audio devices last held a particular audio role
                                        //Console.WriteLine("Audio " + RequestedDeviceType + " Device " + j++ + " = " + CurrentDeviceInfo); // Output the CurrentDeviceInfo to the event log. Useful for debuging
                                        for (int i = 0; i < roles.Length; i++) // Loop based on the size of the roles string array
                                        {
                                            byte[] RegistryData = (byte[])DeviceKey.GetValue(roles[i]); // Extract audio device role data from the registry
                                            if (RegistryData == null) // Check if the extracted data is null
                                                continue; // Continue to next index in parent for loop
                                            CurrentDeviceRoleTimes[i] = GetRoleDateTime(RegistryData); // Retrieve role information from registry, convert this data to a DateTime, and store it
                                            //Console.WriteLine(roles[i] + " = " + CurrentDeviceRoleTimes[i].ToString()); // Output info to event log. Useful for debuging
                                        }
                                        if (ActiveDeviceRoles == null || ActiveDeviceRoles.Length == 0) // Check if ActiveDeviceRoles is null or empty
                                        {
                                            ActiveDeviceRoles = new string[roles.Length]; // Initialize ActiveDeviceRoles string array
                                            ActiveDeviceRoleTimes = new DateTime[roles.Length]; // Initialize ActiveDeviceRoleTImes DateTime array
                                        }
                                        for (int i = 0; i < roles.Length; i++) // Loop based on the size of the roles string array 
                                        {
                                            if (ActiveDeviceRoleTimes[i] < CurrentDeviceRoleTimes[i]) // Check if the ActiveDeviceRoleTime at the current index is less than the CurrentDeviceRoleTime at this index
                                            {
                                                ActiveDeviceRoles[i] = CurrentDeviceInfo; // Set ActiveDeviceRoles at current index to CurrentDeviceInfo
                                                ActiveDeviceRoleTimes[i] = CurrentDeviceRoleTimes[i]; // Set ActiveDeviceRoleTime at current index to corresponding CurrentDeviceRoleTime at this index
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (!String.Equals(RequestedDeviceStatus, "Enabled", StringComparison.OrdinalIgnoreCase)) // Check if user does NOT want to see the enabled devices
            {
                if (ActiveDeviceRoles != null) // Check if ActiveDeviceRoles is not null (i.e., enabled device data has been found and stored)
                {
                    for (int i = 0; i < ActiveDeviceRoles.Length; i++) // Loop based on the size of the ActiveDeviceRoles string array
                    {
                        string RoleName = null; // Initialize string variable for storing role description
                        switch (i) // Create switch statement based on integer i
                        {
                            case 0: // For case where i = 0
                                RoleName = "Default"; // Set RoleName
                                break; // Break out of switch statement
                            case 1: // For case where i = 1
                                    // There is the "Multimedia" role, but I don't believe this is currently used by Windows. 
                                    // The code for this role will remain for possible future use.
                                    //RoleName = "Multimedia"; // Set RoleName
                                    //break; // Break out of switch statement
                                continue; // Immediately continue with next index in parent for loop
                            case 2: // For case where i = 2
                                RoleName = "Communications"; // Set RoleName
                                break; // Break out of switch statement
                        }

                        if (ActiveDeviceRoles[i] == null) // Check if ActiveDeviceRole at current index is null
                            Console.WriteLine("{0} {1} Device = {2}", RoleName, RequestedDeviceType, "Not Set"); // Output info to event log
                        else
                            Console.WriteLine("{0} {1} Device = {2}", RoleName, RequestedDeviceType, ActiveDeviceRoles[i]); // Output info to event log
                    }
                }
                else
                    Console.WriteLine("No audio playback devices enabled"); // Output info to event log
            }
            Console.ReadLine();
        }

        // Function for converting registry data for an audio device into corresponding DateTime information
        static DateTime GetRoleDateTime(byte[] binary)
        {
            if (binary == null || binary.Length != 16) // Check if binary is null or the length is not 16
                throw new ArgumentException("Error converting registry data to DateTime"); // Throw an exception

            int year = Convert.ToInt32(binary[0] + binary[1]*256); // Extract year from registy data
            int month = Convert.ToInt32(binary[2]); // Extract month from registy data
            int day = Convert.ToInt32(binary[6]); // Extract day from registy data
            int hour = Convert.ToInt32(binary[8]); // Extract hour from registy data
            int minute = Convert.ToInt32(binary[10]); // Extract minute from registy data
            int seconds = Convert.ToInt32(binary[12]); // Extract seconds from registy data
            int milliseconds = Convert.ToInt32(binary[14] + binary[15]*256); // Extract milliseconds from registy data
            return new DateTime(year, month, day, hour, minute, seconds, milliseconds).ToLocalTime(); // Return the converted DateTime data
        }
    }
}

// References:
// https://stackoverflow.com/questions/14668091/read-registry-binary-and-convert-to-string
// https://msdn.microsoft.com/en-us/library/system.datetime.frombinary(v=vs.110).aspx
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/382c06b1-a660-47da-a6e6-a7b27404581a/regbinary-value-from-registry-to-date-format-conversion?forum=csharpgeneral
// http://nircmd.nirsoft.net/setdefaultsounddevice.html
// https://stackoverflow.com/questions/3121957/how-can-i-do-a-case-insensitive-string-comparison

感謝@Exergist 的辛勤工作以及對代碼的一些閱讀,我在 Python 中獲得了相同的結果,以便我可以正確使用 pyaudio。 另外,我必須使用 Level:0 而不是 Role:0。 這是我的最終結果

import winreg as wr
import platform


def is_os_64bit():
    return platform.machine().endswith('64')


def get_active_device():
    read_access = wr.KEY_READ | wr.KEY_WOW64_64KEY if is_os_64bit() else wr.KEY_READ
    audio_path = r'SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render'
    child_key = wr.OpenKeyEx(wr.HKEY_LOCAL_MACHINE, audio_path, 0, read_access)
    devices = wr.QueryInfoKey(child_key)[0]
    active_last_used = -1
    active_device_name = None
    for i in range(devices):
        device_key_path = f'{audio_path}\\{wr.EnumKey(child_key, i)}'
        device_key = wr.OpenKeyEx(wr.HKEY_LOCAL_MACHINE, device_key_path, 0, read_access)
        if wr.QueryValueEx(device_key, 'DeviceState')[0] == 1:
            properties_path = f'{device_key_path}\\Properties'
            properties = wr.OpenKeyEx(wr.HKEY_LOCAL_MACHINE, properties_path, 0, read_access)
            device_name = wr.QueryValueEx(properties, '{b3f8fa53-0004-438e-9003-51a46e139bfc},6')[0]
            device_type = wr.QueryValueEx(properties, '{a45c254e-df1c-4efd-8020-67d146a850e0},2')[0]
            pa_name = f'{device_type} ({device_name})'  # name shown in PyAudio
            last_used = wr.QueryValueEx(device_key, 'Level:0')[0]
            if last_used > active_last_used:  # the bigger the number, the more recent it was used
                active_last_used = last_used
                active_device_name = pa_name
    return active_device_name

當前選擇的默認設備將始終顯示為 ID 0。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM