dotfiles/rofi/lib/pactl.py

77 lines
1.6 KiB
Python

from enum import auto, StrEnum
from json import loads
from subprocess import run
from typing import TypedDict, cast
from rofi_menu import FLAG_STYLE_URGENT, Menu, ShellItem
class NodeType(StrEnum):
SINK = auto()
SOURCE = auto()
def _pactl(*args: str) -> str:
return run(["pactl", "--format=json", *args], capture_output=True).stdout.decode()
class Volume(TypedDict):
value: int
value_percent: str
db: str
class Latency(TypedDict):
actual: float
configured: float
class Port(TypedDict):
name: str
description: str
type: str
priority: int
availability_group: str
availability: str
class Node(TypedDict):
index: int
state: str
name: str
description: str
driver: str
sample_specification: str
channel_map: str
owner_module: int
mute: bool
volume: dict[str, Volume]
balance: float
base_volume: Volume
monitor_source: str
latency: Latency
flags: list[str]
properties: dict[str, str]
ports: list[Port]
active_port: str
formats: list[str]
def list_nodes(node_type: NodeType) -> list[Node]:
return cast(list[Node], loads(_pactl("list", f"{node_type}s")))
def get_default(node_type: NodeType) -> str:
return _pactl(f"get-default-{node_type}").strip()
def create_item(node_type: NodeType, node: Node, default: str) -> ShellItem:
return ShellItem(
node["description"],
f"pactl set-default-{node_type} {node["name"]}",
flags=FLAG_STYLE_URGENT if node["name"] == default else None,
show_output=True
)
def create_menu(node_type: NodeType) -> Menu:
default = get_default(node_type)
return Menu(
prompt=f"Select {node_type}",
items=[create_item(node_type, node, default) for node in list_nodes(node_type)]
)