如何以编程方式设置应用程序的默认输入和输出音频设备?

问题描述 投票:0回答:3

如果我转到 Windows 10 (1803) 计算机上的“设置”,我可以访问一个页面(“应用程序音量和设备首选项”),可让我为正在运行的应用程序设置默认输入和输出设备。

如何以编程方式设置这些选项?

相关:

windows winapi com windows-10
3个回答
7
投票

这里可以枚举所有的播放设备

#include <windows.h>
#include <mmsystem.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "Winmm.lib")

int main()
{
    int nSoundCardCount = waveOutGetNumDevs();

    for (int i = 0; i < nSoundCardCount; i++)
    {
        WAVEOUTCAPS woc;
        waveOutGetDevCaps(i, &woc, sizeof(woc));

        cout << woc.szPname << endl; 
    }

    system("pause");
    return 0;
}

这里需要使用PolicyConfig.h和SetDefaultAudioPlaybackDevice添加.h文件和接口。参考这个项目

1.添加头文件PolicyConfig.h

2.添加头文件和接口。

#include "Mmdeviceapi.h"
#include "PolicyConfig.h"
#include "Propidl.h"
#include "Functiondiscoverykeys_devpkey.h"
HRESULT SetDefaultAudioPlaybackDevice( LPCWSTR devID )
{
    IPolicyConfigVista *pPolicyConfig;
    ERole reserved = eConsole;

    HRESULT hr = CoCreateInstance(__uuidof(CPolicyConfigVistaClient), 
        NULL, CLSCTX_ALL, __uuidof(IPolicyConfigVista), (LPVOID *)&pPolicyConfig);
    if (SUCCEEDED(hr))
    {
        hr = pPolicyConfig->SetDefaultEndpoint(devID, reserved);
        pPolicyConfig->Release();
    }
    return hr;
}

3.使用上面的接口编写一个函数来设置默认输出设备。

这是MFC项目。也许你需要改变。

需要设置哪个输出设备,可以自己修改宏的内容。 我使用

waveOutGetDevCaps()

获取输出设备的名称
//Set the default audio playback device 
#define  DEF_AUDIO_NAME _T("Speakers (2- Logitech USB Heads")  //modify it, my device is Speakers (2- Logitech USB Heads

void InitDefaultAudioDevice()
{
    HRESULT hr = CoInitialize(NULL);
    if (SUCCEEDED(hr))
    {
        IMMDeviceEnumerator *pEnum = NULL;
        // Create a multimedia device enumerator.
        hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
            CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnum);
        if (SUCCEEDED(hr))
        {
            //Determine if it is the default audio device
            bool bExit = false;
            IMMDevice  *pDefDevice = NULL;
            hr = pEnum->GetDefaultAudioEndpoint(eRender, eMultimedia,&pDefDevice);
            if (SUCCEEDED(hr))
            {
                IPropertyStore *pStore;
                hr = pDefDevice->OpenPropertyStore(STGM_READ, &pStore);
                if (SUCCEEDED(hr))
                {
                    PROPVARIANT friendlyName;
                    PropVariantInit(&friendlyName);
                    hr = pStore->GetValue(PKEY_Device_FriendlyName, &friendlyName);
                    if (SUCCEEDED(hr))
                    {
                        CString strTmp = friendlyName.pwszVal;
                        if (strTmp.Find(DEF_AUDIO_NAME) != -1)
                        {
                            bExit = true;
                        }
                        PropVariantClear(&friendlyName);
                    }
                    pStore->Release();
                }
                pDefDevice->Release();
            }
            if (bExit)
            {
                pEnum->Release();
                return;
            }

            IMMDeviceCollection *pDevices;
            // Enumerate the output devices.
            hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices);
            if (SUCCEEDED(hr))
            {
                UINT count;
                pDevices->GetCount(&count);
                if (SUCCEEDED(hr))
                {
                    for (int i = 0; i < count; i++)
                    {
                        bool bFind = false;
                        IMMDevice *pDevice;
                        hr = pDevices->Item(i, &pDevice);
                        if (SUCCEEDED(hr))
                        {
                            LPWSTR wstrID = NULL;
                            hr = pDevice->GetId(&wstrID);
                            if (SUCCEEDED(hr))
                            {
                                IPropertyStore *pStore;
                                hr = pDevice->OpenPropertyStore(STGM_READ, &pStore);
                                if (SUCCEEDED(hr))
                                {
                                    PROPVARIANT friendlyName;
                                    PropVariantInit(&friendlyName);
                                    hr = pStore->GetValue(PKEY_Device_FriendlyName, &friendlyName);
                                    if (SUCCEEDED(hr))
                                    {
                                        // if no options, print the device
                                        // otherwise, find the selected device and set it to be default
                                        CString strTmp = friendlyName.pwszVal;
                                        if (strTmp.Find(DEF_AUDIO_NAME) != -1)
                                        {
                                            SetDefaultAudioPlaybackDevice(wstrID);
                                            bFind = true;
                                        }
                                        PropVariantClear(&friendlyName);
                                    }
                                    pStore->Release();
                                }
                            }
                            pDevice->Release();
                        }

                        if (bFind)
                        {
                            break;
                        }
                    }
                }
                pDevices->Release();
            }
            pEnum->Release();
        }
    }
    CoUninitialize();
}

此示例只能更改主音量的输出。不知道能否满足您的要求?如果需要换其他app,还得摸索一段时间。


4
投票

所以我已经使用 SoundVolumeView 一段时间了,它让我可以通过命令行将麦克风静音和取消静音,而且我最近发现(由于 OBS 和监控音频)它还可以更改应用程序的设备或全局默认设备

并使用 /SetDefault 和 /SetAppDefault,如页面底部的文档示例所示

我已将其放入批处理脚本中并将宏绑定到我的键盘,到目前为止效果很好:)


0
投票

@slhad 的回答救了我!我对这个主题进行了大量的挖掘,但无法在 C# 或基本的 powershell 中实现它。然而,使用 SoundVolumeView 我能够实现它。

这是我的 Powershell 脚本,您可以使用它来开始。我的用例是在耳机和扬声器之间切换 Spotify。

# paths
$root = "F:\Programs\Sound Volume View"
$soundVolumeViewPath = "$root\SoundVolumeView.exe"
$deviceFilePath = "$root\current_device"

# audio device root paths
$deviceID1 = "Scarlett Solo USB"
$deviceID2 = "2- High Definition Audio Device"

$currentDeviceID = Get-Content $deviceFilePath

if ($currentDeviceID -eq $deviceID1) {
    $setDeviceID = $deviceID2
} else {
    $setDeviceID = $deviceID1
}

$setDeviceID | Out-File $deviceFilePath

& $soundVolumeViewPath /SetAppDefault "$setDeviceID\Device\Speakers\Render" all "Spotify.exe"

对于我的用例来说,一切都是硬编码的,因此任何未来的漫游者都需要进行一些定制。我的实现从文件中读取,获取“当前”设备,并将 Spotify 的默认音频设备交换到另一个设备。效果很好。

通过使用自动热键我能够将其设置为按键绑定(Win + J):

#Requires AutoHotkey v2.0

#j::Run 'powershell.exe -windowstyle hidden -ExecutionPolicy Bypass -File "F:\Programs\Sound Volume View\spotify.ps1"' ,, "Hide"

我建议将其编译为 exe(这是通过 AHK 完成的),然后将其添加到您的启动目录 (%AppData%\Microsoft\Windows\Start Menu\Programs\Startup) 以便于使用。

© www.soinside.com 2019 - 2024. All rights reserved.