Переключить звук приемник / выход с помощью сочетания клавиш

Я хочу переключаться между приемниками / выходами звука в Ubuntu с помощью ярлыка. Я хочу, чтобы решение работало с любым количеством устройств и переключало все приемники-входы в процессе.

1
задан 11 July 2021 в 14:58

1 ответ

Я хочу предоставить свое решение для всех, кто сможет его использовать и улучшить, так как меня сильно расстроило то, что ни одно из решений (например, Устройство вывода звука, быстрое переключение? ]) работал при любых условиях.

Таким образом, я создал сценарий python с небольшим перебором (и плохими и уродливыми регулярными выражениями) для выполнения этой работы:

#!/usr/bin/env python3
#this little script switches the sound sink on ubuntu
# https://askubuntu.com/questions/156895/how-to-switch-sound-output-with-key-shortcut/1203350#1203350 and https://askubuntu.com/questions/1011806/how-do-i-switch-the-audio-outputs-of-an-audio-device-from-cli?noredirect=1&lq=1 were helpful
import argparse
import logging
import subprocess
import re

#a simple representation of all relevant info of an audio sink for this script
class Sink:
    def __init__(self, index, name, state):
        self.index = index
        self.name = name
        self.state = state
        if state in ["RUNNING", "IDLE"]:
            self.selected = True
        else:
            self.selected = False

    def __str__(self):
        return 'sink\nindex: {self.index}\nname: {self.name}\nstate: {self.state}\nselected: {self.selected}\n'.format(self=self)

#a simple representation of all relevant info of an audio sink-input for this script
class Sink_Input:
    def __init__(self, index, application_name, sink, state):
        self.index = index
        self.application_name = application_name
        self.sink = sink
        self.state = state

    def __str__(self):
        return 'sink-input\nindex: {self.index}\napplication_name: {self.application_name}\nsink: {self.sink}\nstate: {self.state}\n'.format(self=self)

        
def get_sinks():
    pacmd_output = str(subprocess.check_output(["pacmd", "list-sinks"]))
    sinks_raw = pacmd_output.split("index: ")
    sinks = []
    for sink_raw in sinks_raw[1:]:
        index = int(re.findall("^\d+", sink_raw)[0])
        name = re.findall("device.description = \"[^\"]*\"", sink_raw)[0][22:-1]
        state = re.findall("state: [A-Z]*", sink_raw)[0][7:]
        sink = Sink(index, name, state)
        sinks.append(sink)
    return sinks

def get_sink_inputs():
    sink_inputs = []
    pacmd_output = str(subprocess.check_output(["pacmd", "list-sink-inputs"]))
    inputs_raw = pacmd_output.split("index: ")
    for input_raw in inputs_raw[1:]:
        index = int(re.findall("^\d+", input_raw)[0])
        sink = int(re.findall("sink: \d*", input_raw)[0][5:])
        application_name = re.findall("application.name = \"[^\"]*\"", input_raw)[0][20:-1]
        state = re.findall("state: [A-Z]*", input_raw)[0][7:]
        sink_input = Sink_Input(index, application_name, sink, state)
        sink_inputs.append(sink_input)
    return sink_inputs

def switch_to_next_sink(sinks, notify):
    current_sink = None
    next_sink = sinks[0]
    for i in range(len(sinks)):
        if sinks[i].selected:
            current_sink = sinks[i]
            if i == len(sinks) -1:
                next_sink = sinks[0]
            else:
                next_sink = sinks[i+1]
    #switch default sink to next sink
    subprocess.call(["pacmd", "set-default-sink", str(next_sink.index)])
    #move all apps to next sink
    for sink_input in get_sink_inputs():
        subprocess.call(["pacmd", "move-sink-input", str(sink_input.index), str(next_sink.index)])
    if notify:
        subprocess.call(["notify-send", "Changed audio sink", "new audio sink is " + next_sink.name])

def main():
    parser = argparse.ArgumentParser(description='''Switches to the 'next' audio sink on Ubuntu and can provide additional info on sound sinks.
    If no arguments are passed only the next audio sink is selected.
    For ease of use add /usr/bin/python3 /home/sebi/misc/switch_sound_sink.py as keyboard shortcut i.e. Super+Shift+S (Super+O somehow not working) ''')
    parser.add_argument('-s', '--state',
                        help='boiled down output of pacmd list-sinks and list-sink-inputs', action='store_true')
    parser.add_argument('-n', '--notify', help='send notification to the desktop', action='store_true')
    
    logLevelsRange = [logging.NOTSET, logging.DEBUG, logging.INFO, logging.WARN, logging.ERROR, logging.CRITICAL]
    parser.add_argument('-l', '--logLevel', help='the log level', type=int, choices=logLevelsRange,
                        default=logging.INFO)

    args = parser.parse_args()

    if args.state:
        sinks = get_sinks()
        for sink in sinks:
            print(sink)
        sink_inputs = get_sink_inputs()
        for sink_input in sink_inputs:
            print(sink_input)
    else:
        sinks = get_sinks()
        switch_to_next_sink(sinks, args.notify)
        
main()

Я добавил дополнительные уведомления рабочих столов, но не использую их, поскольку они не могут отображаться только временно. ( Как я могу отправить настраиваемое уведомление на рабочий стол? )

1
ответ дан 28 July 2021 в 11:20

Другие вопросы по тегам:

Похожие вопросы: