From 8cedecaa4f75db930e619277d3ea77401984b687 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Mon, 24 Nov 2025 17:20:43 +1300 Subject: [PATCH] add ability to set audio profile before starting a call --- meshchat.py | 21 +++++++++- .../components/telephone/TelephonePage.vue | 39 ++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/meshchat.py b/meshchat.py index 11e26f9..504a0ee 100644 --- a/meshchat.py +++ b/meshchat.py @@ -20,6 +20,7 @@ import RNS import RNS.vendor.umsgpack as msgpack from LXMF import LXMRouter from LXST import Telephone +from LXST.Primitives.Telephony import Profiles from aiohttp import web, WSMessage, WSMsgType, WSCloseCode from peewee import SqliteDatabase from serial.tools import list_ports @@ -412,6 +413,7 @@ class ReticulumMeshChat: timeout_seconds = int(request.query.get("timeout", 15)) input_device_name = request.query.get("input_device_name", None) output_device_name = request.query.get("output_device_name", None) + audio_profile_id = int(request.query.get("audio_profile_id", None)) # convert hash to bytes identity_hash = bytes.fromhex(identity_hash_hex) @@ -462,7 +464,7 @@ class ReticulumMeshChat: self.telephone.set_speaker(output_device_name) # initiate call - AsyncUtils.run_async(asyncio.to_thread(self.telephone.call, destination_identity, None)) + AsyncUtils.run_async(asyncio.to_thread(self.telephone.call, destination_identity, audio_profile_id)) return web.json_response({ "message": "Calling...", @@ -499,6 +501,23 @@ class ReticulumMeshChat: "output_devices": output_devices, }) + # serve list of available audio profiles + @routes.get("/api/v1/telephone/audio-profiles") + async def index(request): + + # get audio profiles + audio_profiles = [] + for available_profile in Profiles.available_profiles(): + audio_profiles.append({ + "id": available_profile, + "name": Profiles.profile_name(available_profile) + }) + + return web.json_response({ + "default_audio_profile_id": Profiles.DEFAULT_PROFILE, + "audio_profiles": audio_profiles, + }) + # fetch com ports @routes.get("/api/v1/comports") async def index(request): diff --git a/src/frontend/components/telephone/TelephonePage.vue b/src/frontend/components/telephone/TelephonePage.vue index e9b934e..a4c0c27 100644 --- a/src/frontend/components/telephone/TelephonePage.vue +++ b/src/frontend/components/telephone/TelephonePage.vue @@ -125,6 +125,18 @@ +
+
+ + + +
+
+ +
+
@@ -241,10 +253,12 @@ export default { selectedInputDevice: null, selectedOutputDevice: null, - inputDevices: [], outputDevices: [], + selectedAudioProfileId: null, + audioProfiles: [], + }; }, mounted: function() { @@ -252,6 +266,7 @@ export default { // update config this.getConfig(); this.getAudioDevices(); + this.getAudioProfiles(); this.getTelephoneStatus(); // update telephone status every second @@ -296,6 +311,12 @@ export default { return; } + // make sure audio profile provided + if(!this.selectedAudioProfileId) { + alert("Please select audio quality."); + return; + } + // show loading this.isInitiatingCall = true; @@ -307,6 +328,7 @@ export default { timeout: 15, // how long to attempt to initiate call input_device_name: this.selectedInputDevice, output_device_name: this.selectedOutputDevice, + audio_profile_id: this.selectedAudioProfileId, }, }); @@ -387,6 +409,21 @@ export default { console.error(e); } }, + async getAudioProfiles() { + try { + + // fetch audio profiles + const response = await axios.get("/api/v1/telephone/audio-profiles"); + + // update ui + this.selectedAudioProfileId = response.data.default_audio_profile_id; + this.audioProfiles = response.data.audio_profiles; + + } catch(e) { + // do nothing on error + console.error(e); + } + }, async getTelephoneStatus() { try {