From 0112f85d343b6c541b22ff3fff764b8554d9d8e1 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Thu, 6 Nov 2025 22:46:22 +0100 Subject: [PATCH] Added low-latency output mode configuration option for LXST voice calls --- sbapp/sideband/core.py | 4 ++++ sbapp/sideband/voice.py | 4 +++- sbapp/ui/voice.py | 31 +++++++++++++++++++++++++++---- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py index e0abe85..76414fe 100644 --- a/sbapp/sideband/core.py +++ b/sbapp/sideband/core.py @@ -906,6 +906,8 @@ class SidebandCore(): self.config["voice_ringer"] = None if not "voice_trusted_only" in self.config: self.config["voice_trusted_only"] = False + if not "voice_low_latency" in self.config: + self.config["voice_low_latency"] = False # Make sure we have a database if not os.path.isfile(self.db_path): @@ -2147,6 +2149,7 @@ class SidebandCore(): elif "telephone_set_speaker" in call: connection.send(self.telephone.set_speaker(call["telephone_set_speaker"])) if self.telephone else False elif "telephone_set_microphone" in call: connection.send(self.telephone.set_microphone(call["telephone_set_microphone"])) if self.telephone else False elif "telephone_set_ringer" in call: connection.send(self.telephone.set_ringer(call["telephone_set_ringer"])) if self.telephone else False + elif "telephone_set_low_latency_output" in call: connection.send(self.telephone.set_low_latency_output(call["telephone_set_low_latency_output"])) if self.telephone else False else: connection.send(None) @@ -5517,6 +5520,7 @@ class SidebandCore(): self.telephone = ReticulumTelephone(self.identity, owner=self, speaker=self.config["voice_output"], microphone=self.config["voice_input"], ringer=self.config["voice_ringer"]) ringtone_path = os.path.join(self.asset_dir, "audio", "notifications", "soft1.opus") self.telephone.set_ringtone(ringtone_path) + self.telephone.set_low_latency_output(self.config["voice_low_latency"]) return True except Exception as e: diff --git a/sbapp/sideband/voice.py b/sbapp/sideband/voice.py index 44cb758..07bbb48 100644 --- a/sbapp/sideband/voice.py +++ b/sbapp/sideband/voice.py @@ -111,6 +111,7 @@ class ReticulumTelephone(): def hangup(self): self.telephone.hangup() def answer(self): self.telephone.answer(self.caller) def set_busy(self, busy): self.telephone.set_busy(busy) + def set_low_latency_output(self, enabled): self.telephone.set_low_latency_output(enabled) def dial(self, identity_hash): self.last_dialled_identity_hash = identity_hash @@ -199,4 +200,5 @@ class ReticulumTelephoneProxy(): def answer(self): return self.owner.service_rpc_request({"telephone_answer": True }) def set_speaker(self, speaker): return self.owner.service_rpc_request({"telephone_set_speaker": speaker }) def set_microphone(self, microphone): return self.owner.service_rpc_request({"telephone_set_microphone": microphone }) - def set_ringer(self, ringer): return self.owner.service_rpc_request({"telephone_set_ringer": ringer }) \ No newline at end of file + def set_ringer(self, ringer): return self.owner.service_rpc_request({"telephone_set_ringer": ringer }) + def set_low_latency_output(self, enabled): return self.owner.service_rpc_request({"telephone_set_low_latency_output": enabled}) \ No newline at end of file diff --git a/sbapp/ui/voice.py b/sbapp/ui/voice.py index 60d19fd..b0f8e9a 100644 --- a/sbapp/ui/voice.py +++ b/sbapp/ui/voice.py @@ -202,8 +202,10 @@ class Voice(): def update_settings_screen(self, sender=None): self.voice_settings_screen.ids.voice_trusted_only.active = self.app.sideband.config["voice_trusted_only"] self.voice_settings_screen.ids.voice_trusted_only.bind(active=self.settings_save_action) + self.voice_settings_screen.ids.voice_low_latency.active = self.app.sideband.config["voice_low_latency"] + self.voice_settings_screen.ids.voice_low_latency.bind(active=self.settings_save_action) - bp = 6; ml = 45; fs = 16; ics = 14 + bp = 6; ml = 38; fs = 16; ics = 14 self.update_devices() # Output devices @@ -216,7 +218,8 @@ class Voice(): for device in self.output_devices: if not device in self.listed_output_devices: - label = device if len(device) < ml else device[:ml-3]+"..." + device_str = device.replace("[", "").replace("]", "") + label = device_str if len(device_str) < ml else device_str[:ml-3]+"..." device_button = MDRectangleFlatIconButton(text=label, font_size=dp(fs), icon_size=dp(ics), on_release=self.output_device_action) device_button.padding = [dp(bp), dp(bp), dp(bp), dp(bp)]; device_button.size_hint = [1.0, None] if self.app.sideband.config["voice_output"] == device: device_button.icon = "check" @@ -234,7 +237,8 @@ class Voice(): for device in self.input_devices: if not device in self.listed_input_devices: - label = device if len(device) < ml else device[:ml-3]+"..." + device_str = device.replace("[", "").replace("]", "") + label = device_str if len(device_str) < ml else device_str[:ml-3]+"..." device_button = MDRectangleFlatIconButton(text=label, font_size=dp(fs), icon_size=dp(ics), on_release=self.input_device_action) device_button.padding = [dp(bp), dp(bp), dp(bp), dp(bp)]; device_button.size_hint = [1.0, None] if self.app.sideband.config["voice_input"] == device: device_button.icon = "check" @@ -252,7 +256,8 @@ class Voice(): for device in self.output_devices: if not device in self.listed_ringer_devices: - label = device if len(device) < ml else device[:ml-3]+"..." + device_str = device.replace("[", "").replace("]", "") + label = device_str if len(device_str) < ml else device_str[:ml-3]+"..." device_button = MDRectangleFlatIconButton(text=label, font_size=dp(fs), icon_size=dp(ics), on_release=self.ringer_device_action) device_button.padding = [dp(bp), dp(bp), dp(bp), dp(bp)]; device_button.size_hint = [1.0, None] if self.app.sideband.config["voice_ringer"] == device: device_button.icon = "check" @@ -262,7 +267,10 @@ class Voice(): def settings_save_action(self, sender=None, event=None): self.app.sideband.config["voice_trusted_only"] = self.voice_settings_screen.ids.voice_trusted_only.active + self.app.sideband.config["voice_low_latency"] = self.voice_settings_screen.ids.voice_low_latency.active self.app.sideband.save_configuration() + if self.app.sideband.telephone: + self.app.sideband.telephone.set_low_latency_output(self.app.sideband.config["voice_low_latency"]) def output_device_action(self, sender=None): self.app.sideband.config["voice_output"] = sender.device @@ -415,6 +423,21 @@ MDScreen: pos_hint: {"center_y": 0.3} active: False + MDBoxLayout: + orientation: "horizontal" + padding: [0,0,dp(24),0] + size_hint_y: None + height: dp(48) + + MDLabel: + text: "Low-latency output" + font_style: "H6" + + MDSwitch: + id: voice_low_latency + pos_hint: {"center_y": 0.3} + active: False + MDLabel: text: "Audio Devices" font_style: "H6"