Developer Referenceaudio_control
_PactlBackend
pactl subprocesses with the same operation set as the bindings.
Functions
func__init__(self, timeout) -> NoneSource Code
def __init__(self, timeout: float) -> None:
self._timeout = timeoutparamselfparamtimeoutfloatReturns
Nonefuncrun(self, *args) -> strRun one pactl command and return its stdout.
Source Code
async def run(self, *args: str) -> str:
"""Run one pactl command and return its stdout.
Raises:
AudioControlError: pactl is missing, failed, or timed out.
"""
logger.debug("pactl fallback: pactl %s", " ".join(args))
return await self._exec(*args)paramselfparamargsstr= ()Returns
strfunc_exec(self, *args) -> strSource Code
async def _exec(self, *args: str) -> str:
env = dict(os.environ, LC_ALL="C", LANGUAGE="C")
try:
proc = await asyncio.create_subprocess_exec(
"pactl", *args, env=env,
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
except Exception as e:
raise AudioControlError(f"pactl unavailable: {e}") from e
try:
out, err = await asyncio.wait_for(proc.communicate(), timeout=self._timeout)
except asyncio.TimeoutError:
# Reap it rather than leaking one blocked pactl per call on a
# stuck server.
with contextlib.suppress(ProcessLookupError):
proc.kill()
await proc.wait()
raise AudioControlError(f"pactl {' '.join(args)} timed out") from None
if proc.returncode != 0:
raise AudioControlError(
f"pactl {' '.join(args)} failed: {err.decode(errors='replace').strip()}")
return out.decode(errors="replace")paramselfparamargsstr= ()Returns
strfuncsink_list(self) -> List[PulseNode]Source Code
async def sink_list(self) -> List[PulseNode]:
return _parse_pactl_list(await self.run("list", "sinks"))paramselfReturns
typing.List[selkies.audio_control.PulseNode]funcsource_list(self) -> List[PulseNode]Source Code
async def source_list(self) -> List[PulseNode]:
return _parse_pactl_list(await self.run("list", "sources"))paramselfReturns
typing.List[selkies.audio_control.PulseNode]funcsource_output_list(self) -> List[PulseNode]Source Code
async def source_output_list(self) -> List[PulseNode]:
return _parse_pactl_list(await self.run("list", "source-outputs"))paramselfReturns
typing.List[selkies.audio_control.PulseNode]funcserver_defaults(self) -> Tuple[Optional[str], Optional[str]]Source Code
async def server_defaults(self) -> Tuple[Optional[str], Optional[str]]:
sink = source = None
for line in (await self.run("info")).splitlines():
key, _, value = line.partition(":")
if key.strip() == "Default Sink":
sink = value.strip() or None
elif key.strip() == "Default Source":
source = value.strip() or None
return sink, sourceparamselfReturns
typing.Tuple[typing.Optional[str], typing.Optional[str]]funcmodule_load(self, name, args) -> intSource Code
async def module_load(self, name: str, args: str) -> int:
out = (await self.run("load-module", name, *args.split())).strip()
if not out.isdigit():
raise AudioControlError(f"load-module {name} returned no index: {out!r}")
return int(out)paramselfparamnamestrparamargsstrReturns
intfuncmodule_unload(self, index) -> NoneSource Code
async def module_unload(self, index: int) -> None:
await self.run("unload-module", str(index))paramselfparamindexintReturns
Nonefuncsink_default_set(self, name) -> NoneSource Code
async def sink_default_set(self, name: str) -> None:
await self.run("set-default-sink", name)paramselfparamnamestrReturns
Nonefuncsource_default_set(self, name) -> NoneSource Code
async def source_default_set(self, name: str) -> None:
await self.run("set-default-source", name)paramselfparamnamestrReturns
Nonefuncsource_output_move(self, output_index, source_index) -> NoneSource Code
async def source_output_move(self, output_index: int, source_index: int) -> None:
await self.run("move-source-output", str(output_index), str(source_index))paramselfparamoutput_indexintparamsource_indexintReturns
None