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
|
return cmd
|
||||||
if shutil.which("pw-record"):
|
if shutil.which("pw-record"):
|
||||||
cmd = [
|
cmd = [
|
||||||
"pw-record", "--raw", f"--rate={RATE}",
|
"pw-record", *_pw_record_raw_option(), f"--rate={RATE}",
|
||||||
f"--channels={CHANNELS}", "--format=s16",
|
f"--channels={CHANNELS}", "--format=s16",
|
||||||
]
|
]
|
||||||
if target:
|
if target:
|
||||||
@@ -455,6 +455,28 @@ def _pulse_record(target):
|
|||||||
return []
|
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):
|
def _pulse_meeting(mic_target, system_target):
|
||||||
return [
|
return [
|
||||||
"ffmpeg", "-hide_banner", "-nostdin", "-loglevel", "error",
|
"ffmpeg", "-hide_banner", "-nostdin", "-loglevel", "error",
|
||||||
|
|||||||
@@ -238,6 +238,14 @@ class FakeProcess:
|
|||||||
class RecordingCommand(OnLinux, DikteTest):
|
class RecordingCommand(OnLinux, DikteTest):
|
||||||
"""Which program captures the microphone, and how it is asked to."""
|
"""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):
|
def test_parec_is_preferred(self):
|
||||||
"""It speaks to PulseAudio and to PipeWire's compatibility service, so
|
"""It speaks to PulseAudio and to PipeWire's compatibility service, so
|
||||||
it is the one that works on both desktops."""
|
it is the one that works on both desktops."""
|
||||||
@@ -288,9 +296,45 @@ class RecordingCommand(OnLinux, DikteTest):
|
|||||||
if arg.startswith(flag)])
|
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):
|
class RecorderChain(OnLinux, DikteTest):
|
||||||
"""Start to WAV, with pw-record faked out."""
|
"""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):
|
def record(self, data, target="", max_seconds=300):
|
||||||
recorder = audio.Recorder()
|
recorder = audio.Recorder()
|
||||||
results = []
|
results = []
|
||||||
|
|||||||
Reference in New Issue
Block a user