AutoHotKey v2 音频输出设备切换

huangapple go评论94阅读模式
英文:

AutoHotKey v2 Audio Output Device Toggle

问题

以下是您要翻译的部分:

我正在尝试使用AutoHotKey **v2**创建一个热键,使用`nircmd setdefaultsound`来切换音频输出选项。以下是我拥有的程序:它没有出现错误,并且显示了MsgBox,但它总是显示“Headphones”,实际上没有更改设备。

#Requires AutoHotkey v2.0
;一切都在第一个return之前自动运行
device := "Speakers"
return

;音频输出设备切换
#+a::
{
if (device = "Speakers") 
    device := "Headphones"
else if (device = "Headphones") 
    device := "Speakers"
MsgBox Format("所选设备:{}", device)
run "nircmd.exe setdefaultsounddevice %device%"
}

造成这个不起作用的原因是什么?

英文:

I am trying to make a hotkey using AutoHotKey v2 that toggles through the audio output options using nircmd setdefaultsound. The following program is what I have: it does not give errors, and it gives the MsgBox but it always says "Headphones" and it does not actually change the device.

#Requires AutoHotkey v2.0
;Everything until the first return autoruns
device := "Speakers"
return

; Audio Output Device Toggle
#+a::
{
if (device = "Speakers") 
    device := "Headphones"
else if (device = "Headphones") 
    device := "Speakers"
MsgBox Format("Selected device: {}", device)
run "nircmd.exe setdefaultsounddevice %device%"
}

What is causing this not to work?

答案1

得分: 2

你的变量 device 不在该热键的范围内。你需要明确声明你正在使用全局范围的变量。或者在这种情况下,你真正想要的是热键范围内的静态变量。(关于本地和全局)

而且,你试图在字符串内部使用传统的 AHK 语法引用变量。即使在字符串内部,也绝对不可能奏效。以下是一个修复后的脚本,虽然我无法评论你在使用 nircmd 方面的操作。我不使用它,所以我不知道它是否会起作用。

#Requires AutoHotkey v2.0
; 第一个 return 之前的所有内容会自动运行
;device := "Speakers"
return

; 切换音频输出设备
#+a::
{
    ; 全局变量 device 用于全局范围引用
    static device := "Speakers" ; 使用静态变量

    if (device = "Speakers")
        device := "Headphones"
    else if (device = "Headphones")
        device := "Speakers"

    MsgBox("选定的设备:" device)
    Run("nircmd.exe setdefaultsounddevice " device)
}
英文:

Your variable device is not in that hotkey's scope. You'd have to explicitly state that you're using a variable from the global scope. Or in this case what you really want is a static variable in the hotkey's scope.<sup>(about local and global)</sup>

And also, you're trying to use the legacy AHK syntax for referring to a variable. And even while inside a string. There's absolutely no way that could work. Here's a fixed script, although I can't comment on what you're doing with nircmd. I don't use it, so I won't know if it will work.

#Requires AutoHotkey v2.0
;Everything until the first return autoruns
;device := &quot;Speakers&quot;
return

; Audio Output Device Toggle
#+a::
{
	;global device ;to refer from global scope
	static device := &quot;Speakers&quot; ;use a static variable

	if (device = &quot;Speakers&quot;)
		device := &quot;Headphones&quot;
	else if (device = &quot;Headphones&quot;)
		device := &quot;Speakers&quot;

	MsgBox(&quot;Selected device: &quot; device)
	Run(&quot;nircmd.exe setdefaultsounddevice &quot; device)
}

答案2

得分: 0

不要翻译的部分:代码部分

以下是翻译的部分:

一方面,您始终通过将 device 设置为 &quot;Speakers&quot; 来开始,然后检查它是否在 If 语句中,然后将其设置为 &quot;Headphones&quot;,其中 MsgBox 显示如此。

您永远无法进入 else if,因为 device 从不以 Headphones 开始。

而且,即使在您的编辑中将该行移动到热键上方,问题是,如果您在没有热键的情况下更改设备,那么变量将不再正确。

也许可以替换为某个命令,该命令将返回实际的“正在使用”设备?我使用 VA.ahk 在 https://www.autohotkey.com/board/topic/21984-vista-audio-control-functions/ 上进行此类操作。

您还可以快速编写一个 Python 代码以获取信息(如 https://stackoverflow.com/questions/6438628/get-default-audio-video-device 中所引用):

import winreg as wr
import platform
from contextlib import suppress

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

def get_default_output_device():
    """返回默认输出设备的PyAudio格式名称"""
    import winreg as wr
    read_access = wr.KEY_READ | wr.KEY_WOW64_64KEY if is_os_64bit() else wr.KEY_READ
    audio_path = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\MMDevices\\Audio\\Render'
    audio_key = wr.OpenKeyEx(wr.HKEY_LOCAL_MACHINE, audio_path, 0, read_access)
    num_devices = wr.QueryInfoKey(audio_key)[0]
    active_last_used, active_device_name = -1, None
    for i in range(num_devices):
        device_key_path = f'{audio_path}\\{wr.EnumKey(audio_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})'  # PyAudio显示的名称
            with suppress(FileNotFoundError):
                last_used = wr.QueryValueEx(device_key, 'Level:0')[0]
                if last_used > active_last_used:  # 数字越大,最近使用的次数越多
                    active_last_used = last_used
                    active_device_name = pa_name
    return active_device_name
# 打印 (get_default_output_device())  # 在控制台中取消注释以进行测试

希望对您有所帮助。

英文:

For one thing, you are always starting out by setting device to &quot;Speakers&quot; and then checking that it is in the If statement and thus setting it to &quot;Headphones&quot; wherein the MsgBox says so.

You never get to the else if because the device never starts out as Headphones.

And even after you moved that line to above the hotkey in your edits, the problem is, if you change the device without the hot key the variable will no longer be correct.

Maybe replace with some command that would return the actual "in-use" device? I use VA.ahk at https://www.autohotkey.com/board/topic/21984-vista-audio-control-functions/ for this kind of thing.

You could also do a quick python code to get the info (as referenced here https://stackoverflow.com/questions/6438628/get-default-audio-video-device):

import winreg as wr
import platform
from contextlib import suppress

def is_os_64bit():
    return platform.machine().endswith(&#39;64&#39;)

def get_default_output_device():
    &quot;&quot;&quot; returns the PyAudio formatted name of the default output device &quot;&quot;&quot;
    import winreg as wr
    read_access = wr.KEY_READ | wr.KEY_WOW64_64KEY if is_os_64bit() else wr.KEY_READ
    audio_path = &#39;SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\MMDevices\\Audio\\Render&#39;
    audio_key = wr.OpenKeyEx(wr.HKEY_LOCAL_MACHINE, audio_path, 0, read_access)
    num_devices = wr.QueryInfoKey(audio_key)[0]
    active_last_used, active_device_name = -1, None
    for i in range(num_devices):
        device_key_path = f&#39;{audio_path}\\{wr.EnumKey(audio_key, i)}&#39;
        device_key = wr.OpenKeyEx(wr.HKEY_LOCAL_MACHINE, device_key_path, 0, read_access)
        if wr.QueryValueEx(device_key, &#39;DeviceState&#39;)[0] == 1:  # if enabled
            properties_path = f&#39;{device_key_path}\\Properties&#39;
            properties = wr.OpenKeyEx(wr.HKEY_LOCAL_MACHINE, properties_path, 0, read_access)
            device_name = wr.QueryValueEx(properties, &#39;{b3f8fa53-0004-438e-9003-51a46e139bfc},6&#39;)[0]
            device_type = wr.QueryValueEx(properties, &#39;{a45c254e-df1c-4efd-8020-67d146a850e0},2&#39;)[0]
            pa_name = f&#39;{device_type} ({device_name})&#39;  # name shown in PyAudio
            with suppress(FileNotFoundError):
                last_used = wr.QueryValueEx(device_key, &#39;Level:0&#39;)[0]
                if last_used &gt; 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
# print (get_default_output_device())  # uncomment to test in console

hth

huangapple
  • 本文由 发表于 2023年3月3日 22:59:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75628648.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定