mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Merge pull request #16 from hakanekin/fix/pw-record-raw-compat
Handle pw-record versions without --raw support
This commit is contained in:
@@ -445,7 +445,7 @@ def _pulse_record(target):
|
||||
return cmd
|
||||
if shutil.which("pw-record"):
|
||||
cmd = [
|
||||
"pw-record", "--raw", f"--rate={RATE}",
|
||||
"pw-record", *_pw_record_raw_option(), f"--rate={RATE}",
|
||||
f"--channels={CHANNELS}", "--format=s16",
|
||||
]
|
||||
if target:
|
||||
@@ -455,6 +455,28 @@ def _pulse_record(target):
|
||||
return []
|
||||
|
||||
|
||||
def _pw_record_raw_option():
|
||||
"""Use --raw only on pw-record releases that provide it.
|
||||
|
||||
PipeWire gained --raw in 1.4, and in the same release stopped treating a
|
||||
filename of "-" as raw on its own: before it, the option is refused and the
|
||||
recorder dies before any sound arrives; after it, leaving the option out
|
||||
wraps the stream in a container the rest of this file would read as noise.
|
||||
Ubuntu 24.04 and anything else still on 1.0 or 1.2 sit on the near side of
|
||||
that line, so ask the installed binary which form it understands.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["pw-record", "--help"], capture_output=True, text=True, timeout=2
|
||||
)
|
||||
help_text = (result.stdout or "") + (result.stderr or "")
|
||||
except (subprocess.SubprocessError, OSError):
|
||||
return ["--raw"] # preserve the existing command when probing itself fails
|
||||
if not help_text.strip():
|
||||
return ["--raw"]
|
||||
return ["--raw"] if "--raw" in help_text else []
|
||||
|
||||
|
||||
def _pulse_meeting(mic_target, system_target):
|
||||
return [
|
||||
"ffmpeg", "-hide_banner", "-nostdin", "-loglevel", "error",
|
||||
|
||||
@@ -238,6 +238,14 @@ class FakeProcess:
|
||||
class RecordingCommand(OnLinux, DikteTest):
|
||||
"""Which program captures the microphone, and how it is asked to."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
# Whether pw-record takes --raw is read off the installed binary, and
|
||||
# what is being tested here is the command rather than the machine the
|
||||
# test is running on. PwRecordRawOption covers the reading itself.
|
||||
self.enterContext(mock.patch.object(
|
||||
audio, "_pw_record_raw_option", return_value=["--raw"]))
|
||||
|
||||
def test_parec_is_preferred(self):
|
||||
"""It speaks to PulseAudio and to PipeWire's compatibility service, so
|
||||
it is the one that works on both desktops."""
|
||||
@@ -288,9 +296,45 @@ class RecordingCommand(OnLinux, DikteTest):
|
||||
if arg.startswith(flag)])
|
||||
|
||||
|
||||
class PwRecordRawOption(DikteTest):
|
||||
"""Two pw-record generations want opposite commands for the same stream.
|
||||
|
||||
PipeWire 1.4 added --raw and stopped treating a filename of "-" as raw on
|
||||
its own, so the option is refused by everything older and needed by
|
||||
everything newer. The help text is the only thing that tells them apart.
|
||||
"""
|
||||
|
||||
def option(self, **run):
|
||||
with mock.patch.object(audio.subprocess, "run", **run):
|
||||
return audio._pw_record_raw_option()
|
||||
|
||||
def test_a_version_that_offers_raw_is_asked_for_it(self):
|
||||
self.assertEqual(["--raw"], self.option(
|
||||
return_value=FakeCompleted(stdout=" -a, --raw RAW mode\n")))
|
||||
|
||||
def test_a_version_without_it_is_not(self):
|
||||
self.assertEqual([], self.option(
|
||||
return_value=FakeCompleted(stdout=" --rate Sample rate\n")))
|
||||
|
||||
def test_help_that_could_not_be_read_keeps_the_option(self):
|
||||
"""Whatever is installed, the command that worked before this check
|
||||
existed is the safer guess."""
|
||||
self.assertEqual(["--raw"], self.option(side_effect=OSError))
|
||||
self.assertEqual(["--raw"], self.option(
|
||||
side_effect=subprocess.TimeoutExpired("pw-record", 2)))
|
||||
|
||||
def test_help_that_said_nothing_keeps_it_too(self):
|
||||
self.assertEqual(["--raw"], self.option(return_value=FakeCompleted()))
|
||||
|
||||
|
||||
class RecorderChain(OnLinux, DikteTest):
|
||||
"""Start to WAV, with pw-record faked out."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.enterContext(mock.patch.object(
|
||||
audio, "_pw_record_raw_option", return_value=["--raw"]))
|
||||
|
||||
def record(self, data, target="", max_seconds=300):
|
||||
recorder = audio.Recorder()
|
||||
results = []
|
||||
|
||||
Reference in New Issue
Block a user