Fixed notifications not displaying on windows. Ignore accidental PTT presses. Cleaned up file path resolution.

This commit is contained in:
Mark Qvist 2025-11-27 11:11:58 +01:00
commit 424c2fcd06
4 changed files with 104 additions and 126 deletions

View file

@ -102,15 +102,14 @@ def apply_ui_scale():
try:
if RNS.vendor.platformutils.is_android():
import plyer
ui_scale_path = plyer.storagepath.get_application_dir()+"/io.unsigned.sideband/files/app_storage/ui_scale"
ui_scale_path = os.path.join(plyer.storagepath.get_application_dir(), "io.unsigned.sideband", "files", "app_storage", "ui_scale")
else:
if config_path == None:
import sbapp.plyer as plyer
ui_scale_path = plyer.storagepath.get_home_dir()+"/.config/sideband/app_storage/ui_scale"
if ui_scale_path.startswith("file://"):
ui_scale_path = ui_scale_path.replace("file://", "")
ui_scale_path = os.path.join(plyer.storagepath.get_home_dir(), ".config", "sideband", "app_storage", "ui_scale")
if ui_scale_path.startswith("file://"): ui_scale_path = ui_scale_path.replace("file://", "")
else:
ui_scale_path = config_path+"/app_storage/ui_scale"
ui_scale_path = os.path.join(config_path, "app_storage", "ui_scale")
if ui_scale_path:
ui_scale_path = f"{ui_scale_path}{res_ident}"
@ -449,8 +448,8 @@ else:
from android.permissions import request_permissions, check_permission
from android.storage import primary_external_storage_path, secondary_external_storage_path
import pyogg
from pydub import AudioSegment
import LXST.Codecs.libs.pyogg as pyogg
from LXST.Codecs.libs.pydub import AudioSegment
from kivymd.utils.set_bars_colors import set_bars_colors
android_api_version = autoclass('android.os.Build$VERSION').SDK_INT
@ -473,8 +472,8 @@ else:
from .ui.helpers import ContentNavigationDrawer, DrawerList, IconListItem
from .ui.helpers import multilingual_markup, mdc
import sbapp.pyogg as pyogg
from sbapp.pydub import AudioSegment
import LXST.Codecs.libs.pyogg as pyogg
from LXST.Codecs.libs.pydub import AudioSegment
from kivymd.toast import toast
@ -572,6 +571,7 @@ class SidebandApp(MDApp):
self.attach_dialog = None
self.shared_attach_dialog = None
self.rec_dialog = None
self.recording_started = None
self.last_msg_audio = None
self.msg_sound = None
self.audio_msg_mode = LXMF.AM_OPUS_OGG
@ -581,8 +581,8 @@ class SidebandApp(MDApp):
Window.softinput_mode = "below_target"
self.window_state = app_init_window_state
self.icon = self.sideband.asset_dir+"/icon.png"
self.notification_icon = self.sideband.asset_dir+"/notification_icon.png"
self.icon = os.path.join(self.sideband.asset_dir, "icon.png")
self.notification_icon = os.path.join(self.sideband.asset_dir, "notification_icon.png")
self.resume_event_scheduler = None
self.connectivity_updater = None
@ -830,40 +830,40 @@ class SidebandApp(MDApp):
def font_config(self):
from kivy.core.text import LabelBase, DEFAULT_FONT
fb_path = self.sideband.asset_dir+"/fonts/"
fb_path = os.path.join(self.sideband.asset_dir, "fonts")
LabelBase.register(name="hebrew",
fn_regular=fb_path+"NotoSansHebrew-Regular.ttf",
fn_bold=fb_path+"NotoSansHebrew-Bold.ttf",)
fn_regular=os.path.join(fb_path, "NotoSansHebrew-Regular.ttf"),
fn_bold=os.path.join(fb_path, "NotoSansHebrew-Bold.ttf"))
LabelBase.register(name="japanese",
fn_regular=fb_path+"NotoSansJP-Regular.ttf")
fn_regular=os.path.join(fb_path, "NotoSansJP-Regular.ttf"))
LabelBase.register(name="chinese",
fn_regular=fb_path+"NotoSansSC-Regular.ttf")
fn_regular=os.path.join(fb_path, "NotoSansSC-Regular.ttf"))
LabelBase.register(name="korean",
fn_regular=fb_path+"NotoSansKR-Regular.ttf")
fn_regular=os.path.join(fb_path, "NotoSansKR-Regular.ttf"))
LabelBase.register(name="emoji",
fn_regular=fb_path+"NotoEmoji-Regular.ttf")
fn_regular=os.path.join(fb_path, "NotoEmoji-Regular.ttf"))
LabelBase.register(name="defaultinput",
fn_regular=fb_path+"DefaultInput.ttf")
fn_regular=os.path.join(fb_path, "DefaultInput.ttf"))
LabelBase.register(name="combined",
fn_regular=fb_path+"NotoSans-Regular.ttf",
fn_bold=fb_path+"NotoSans-Bold.ttf",
fn_italic=fb_path+"NotoSans-Italic.ttf",
fn_bolditalic=fb_path+"NotoSans-BoldItalic.ttf")
fn_regular=os.path.join(fb_path, "NotoSans-Regular.ttf"),
fn_bold=os.path.join(fb_path, "NotoSans-Bold.ttf"),
fn_italic=os.path.join(fb_path, "NotoSans-Italic.ttf"),
fn_bolditalic=os.path.join(fb_path, "NotoSans-BoldItalic.ttf"))
LabelBase.register(name="mono",
fn_regular=fb_path+"RobotoMonoNerdFont-Regular.ttf")
fn_regular=os.path.join(fb_path, "RobotoMonoNerdFont-Regular.ttf"))
LabelBase.register(name="term",
fn_regular=fb_path+"BigBlueTerm437NerdFont-Regular.ttf")
fn_regular=os.path.join(fb_path, "BigBlueTerm437NerdFont-Regular.ttf"))
LabelBase.register(name="nf",
fn_regular=fb_path+"RobotoMonoNerdFont-Regular.ttf")
fn_regular=os.path.join(fb_path, "RobotoMonoNerdFont-Regular.ttf"))
def update_input_language(self):
language = self.sideband.config["input_language"]
@ -1001,7 +1001,7 @@ class SidebandApp(MDApp):
def share_image(self, image, filename):
if RNS.vendor.platformutils.get_platform() == "android":
save_path = self.sideband.exports_dir
file_path = save_path+"/"+filename
file_path = os.path.join(save_path, filename)
try:
if not os.path.isdir(save_path):
@ -1440,11 +1440,9 @@ class SidebandApp(MDApp):
self.sideband.lxm_ingest_uri(lxm_uri)
def build(self):
FONT_PATH = self.sideband.asset_dir+"/fonts"
if RNS.vendor.platformutils.is_darwin():
self.icon = self.sideband.asset_dir+"/icon_macos_formed.png"
else:
self.icon = self.sideband.asset_dir+"/icon.png"
FONT_PATH = os.path.join(self.sideband.asset_dir, "fonts")
if RNS.vendor.platformutils.is_darwin(): self.icon = os.path.join(self.sideband.asset_dir, "icon_macos_formed.png")
else: self.icon = os.path.join(self.sideband.asset_dir, "icon.png")
self.announces_view = None
@ -2422,11 +2420,11 @@ class SidebandApp(MDApp):
return
if audio_field[0] == LXMF.AM_OPUS_OGG:
temp_path = self.sideband.rec_cache+"/msg.ogg"
temp_path = os.path.join(self.sideband.rec_cache, "msg.ogg")
with open(temp_path, "wb") as af: af.write(self.last_msg_audio)
elif audio_field[0] >= LXMF.AM_CODEC2_700C and audio_field[0] <= LXMF.AM_CODEC2_3200:
temp_path = self.sideband.rec_cache+"/msg.ogg"
temp_path = os.path.join(self.sideband.rec_cache, "msg.ogg")
from sideband.audioproc import samples_to_ogg, decode_codec2, detect_codec2
target_rate = 48000
@ -2459,11 +2457,12 @@ class SidebandApp(MDApp):
if self.sideband.ui_recording: return
self.sideband.ui_started_recording()
self.recording_started = time.time()
if self.sideband.config["hq_ptt"]: self.audio_msg_mode = LXMF.AM_OPUS_OGG
else: self.audio_msg_mode = LXMF.AM_CODEC2_2400
if not hasattr(self, "ptt_recorder") or self.ptt_recorder == None:
self.ptt_recording_path = self.sideband.rec_cache+"/ptt_recording.ogg"
self.ptt_recording_path = os.path.join(self.sideband.rec_cache, "ptt_recording.ogg")
self.ptt_recorder = FileRecorder(self.ptt_recording_path, profile=Opus.PROFILE_VOICE_HIGH, gain=2.0,
skip=0.075, ease_in=0.125, filters=[BandPass(300, 8500), AGC(target_level=-15.0)])
@ -2488,6 +2487,7 @@ class SidebandApp(MDApp):
el_button.line_color=mdc("BlueGray","500")
el_icon.theme_text_color="Custom"
el_icon.text_color=mdc("BlueGray","500")
def job():
try:
self.ptt_recorder.stop()
@ -2497,9 +2497,16 @@ class SidebandApp(MDApp):
RNS.trace_exception(e)
self.sideband.ui_stopped_recording()
if self.message_process_audio(self.ptt_recording_path):
if self.outbound_mode_command: self.outbound_mode_reset()
self.message_send_action()
if self.recording_started != None:
duration = time.time() - self.recording_started
self.recording_started = None
if duration < 0.6: RNS.log(f"Discarding recording, only {RNS.prettyshorttime(duration)} of audio", RNS.LOG_WARNING)
else:
if os.path.isfile(self.ptt_recording_path):
if self.message_process_audio(self.ptt_recording_path):
if self.outbound_mode_command: self.outbound_mode_reset()
self.message_send_action()
threading.Thread(target=job, daemon=True).start()
def message_process_audio(self, input_path):
@ -2546,7 +2553,7 @@ class SidebandApp(MDApp):
ap_duration = time.time() - ap_start
RNS.log("Audio processing complete in "+RNS.prettytime(ap_duration), RNS.LOG_DEBUG)
export_path = self.sideband.rec_cache+"/recording.enc"
export_path = os.path.join(self.sideband.rec_cache, "recording.enc")
with open(export_path, "wb") as export_file:
export_file.write(encoded)
self.attach_path = export_path
@ -2658,7 +2665,7 @@ class SidebandApp(MDApp):
self.rec_dialog.rec_item = rec_item
self.rec_dialog.play_item = play_item
self.rec_dialog.save_item = save_item
self.rec_dialog.file_path = self.sideband.rec_cache+"/recording.ogg"
self.rec_dialog.file_path = os.path.join(self.sideband.rec_cache, "recording.ogg")
def message_record_audio_action(self):
ss = int(dp(18))
@ -3178,7 +3185,7 @@ class SidebandApp(MDApp):
threading.Thread(target=lj, daemon=True).start()
self.information_screen.ids.information_scrollview.effect_cls = ScrollEffect
self.information_screen.ids.information_logo.icon = self.sideband.asset_dir+"/rns_256.png"
self.information_screen.ids.information_logo.icon = os.path.join(self.sideband.asset_dir, "rns_256.png")
str_comps = " - [b]Reticulum[/b] (Reticulum License)\n - [b]LXMF[/b] (Reticulum License)\n - [b]KivyMD[/b] (MIT License)"
str_comps += "\n - [b]Kivy[/b] (MIT License)\n - [b]Codec2[/b] (LGPL License)\n - [b]PyCodec2[/b] (BSD-3 License)"

View file

@ -1,6 +1,5 @@
import os
import io
import sh
import math
import time
import struct
@ -9,15 +8,11 @@ import RNS
import LXMF
if RNS.vendor.platformutils.is_android():
from pyogg import OpusFile, OpusBufferedEncoder, OggOpusWriter
from pydub import AudioSegment
from LXST.Codecs.libs.pyogg import OpusFile, OpusBufferedEncoder, OggOpusWriter
from LXST.Codecs.libs.pydub import AudioSegment
else:
if RNS.vendor.platformutils.is_linux():
from sbapp.pyogg import OpusFile, OpusBufferedEncoder, OggOpusWriter
else:
from pyogg import OpusFile, OpusBufferedEncoder, OggOpusWriter
from sbapp.pydub import AudioSegment
from LXST.Codecs.libs.pyogg import OpusFile, OpusBufferedEncoder, OggOpusWriter
from LXST.Codecs.libs.pydub import AudioSegment
codec2_modes = {
# LXMF.AM_CODEC2_450PWB: ???, # No bindings
@ -102,30 +97,8 @@ def samples_to_wav(samples=None, file_path=None):
def voice_processing(input_path):
try:
return None
# Moving to LXST native processing
# ffmpeg = None
# ffmpeg = sh.ffmpeg
# if ffmpeg:
# filters = "atrim=start=0.075, afade=t=in:st=0:d=0.085, highpass=f=250, lowpass=f=3000, speechnorm=e=12.5:r=0.0001:l=1"
# output_bitrate = "12k"
# opus_apptype = "audio"
# output_path = input_path.replace(".ogg","")+".p.ogg"
# args = [
# "-i", input_path, "-filter:a", filters,
# "-c:a", "libopus", "-application", opus_apptype,
# "-vbr", "on","-b:a", output_bitrate, output_path]
# try:
# try:
# os.unlink(output_path)
# except:
# pass
# ffmpeg(*args)
# return output_path
# except Exception as e:
# RNS.log("Could not process audio with ffmpeg", RNS.LOG_ERROR)
# RNS.trace_exception(e)
# return None
return None
except Exception as e:
return None

View file

@ -202,13 +202,12 @@ class SidebandCore():
self.default_config_template = rns_config
if config_path == None:
self.app_dir = plyer.storagepath.get_home_dir()+"/.config/sideband"
if self.app_dir.startswith("file://"):
self.app_dir = self.app_dir.replace("file://", "")
self.app_dir = os.path.join(plyer.storagepath.get_home_dir(), ".config", "sideband")
if self.app_dir.startswith("file://"): self.app_dir = self.app_dir.replace("file://", "")
else:
self.app_dir = config_path
self.cache_dir = self.app_dir+"/cache"
self.cache_dir = os.path.join(self.app_dir, "cache")
self.rns_configdir = rns_config_path
@ -217,10 +216,10 @@ class SidebandCore():
core_path = core_path.replace("core.pyc", "core.py")
if RNS.vendor.platformutils.is_android():
self.app_dir = android_app_dir+"/io.unsigned.sideband/files/"
self.cache_dir = self.app_dir+"/cache"
self.rns_configdir = self.app_dir+"/app_storage/reticulum"
self.asset_dir = self.app_dir+"/app/assets"
self.app_dir = os.path.join(android_app_dir, "io.unsigned.sideband", "files")
self.cache_dir = os.path.join(self.app_dir, "cache")
self.rns_configdir = os.path.join(self.app_dir, "app_storage", "reticulum")
self.asset_dir = os.path.join(self.app_dir, "app", "assets")
elif RNS.vendor.platformutils.is_darwin():
self.asset_dir = core_path.replace("/sideband/core.py", "/assets")
elif RNS.vendor.platformutils.get_platform() == "linux":
@ -228,40 +227,41 @@ class SidebandCore():
elif RNS.vendor.platformutils.is_windows():
self.asset_dir = core_path.replace("\\sideband\\core.py", "\\assets")
else:
self.asset_dir = plyer.storagepath.get_application_dir()+"/sbapp/assets"
self.asset_dir = os.path.join(plyer.storagepath.get_application_dir(), "sbapp", "assets")
self.map_cache = self.cache_dir+"/maps"
self.map_cache = os.path.join(self.cache_dir, "maps")
if not os.path.isdir(self.map_cache):
os.makedirs(self.map_cache)
self.rec_cache = self.cache_dir+"/rec"
self.rec_cache = os.path.join(self.cache_dir, "rec")
if not os.path.isdir(self.rec_cache):
os.makedirs(self.rec_cache)
self.share_cache = self.cache_dir+"/share"
self.share_cache = os.path.join(self.cache_dir, "share")
if not os.path.isdir(self.share_cache):
os.makedirs(self.share_cache)
self.icon = self.asset_dir+"/icon.png"
self.icon_48 = self.asset_dir+"/icon_48.png"
self.icon_32 = self.asset_dir+"/icon_32.png"
self.icon_macos = self.asset_dir+"/icon_macos.png"
self.notification_icon = self.asset_dir+"/notification_icon.png"
self.notif_icon_black = self.asset_dir+"/notification_icon_black.png"
self.icon = os.path.join(self.asset_dir, "icon.png")
self.icon_48 = os.path.join(self.asset_dir, "icon_48.png")
self.icon_32 = os.path.join(self.asset_dir, "icon_32.png")
self.icon_macos = os.path.join(self.asset_dir, "icon_macos.png")
self.icon_windows = os.path.join(self.asset_dir, "icon.ico")
self.notification_icon = os.path.join(self.asset_dir, "notification_icon.png")
self.notif_icon_black = os.path.join(self.asset_dir, "notification_icon_black.png")
os.environ["TELEMETER_GEOID_PATH"] = os.path.join(self.asset_dir, "geoids")
if not os.path.isdir(self.app_dir+"/app_storage"):
os.makedirs(self.app_dir+"/app_storage")
if not os.path.isdir(os.path.join(self.app_dir, "app_storage")):
os.makedirs(os.path.join(self.app_dir, "app_storage"))
self.config_path = self.app_dir+"/app_storage/sideband_config"
self.identity_path = self.app_dir+"/app_storage/primary_identity"
self.db_path = self.app_dir+"/app_storage/sideband.db"
self.lxmf_storage = self.app_dir+"/app_storage/"
self.log_dir = self.app_dir+"/app_storage/"
self.tmp_dir = self.app_dir+"/app_storage/tmp"
self.exports_dir = self.app_dir+"/exports"
self.telemetry_exclude_path = self.app_dir+"/app_storage/collector_response_excluded"
self.config_path = os.path.join(self.app_dir, "app_storage", "sideband_config")
self.identity_path = os.path.join(self.app_dir, "app_storage", "primary_identity")
self.db_path = os.path.join(self.app_dir, "app_storage", "sideband.db")
self.lxmf_storage = os.path.join(self.app_dir, "app_storage")
self.log_dir = os.path.join(self.app_dir, "app_storage")
self.tmp_dir = os.path.join(self.app_dir, "app_storage", "tmp")
self.exports_dir = os.path.join(self.app_dir, "exports")
self.telemetry_exclude_path = os.path.join(self.app_dir, "app_storage", "collector_response_excluded")
if RNS.vendor.platformutils.is_android():
self.webshare_dir = "./share/"
@ -269,8 +269,8 @@ class SidebandCore():
sideband_dir = os.path.dirname(os.path.abspath(__file__))
self.webshare_dir = os.path.abspath(os.path.join(sideband_dir, "..", "share"))
self.webshare_ssl_key_path = self.app_dir+"/app_storage/ssl_key.pem"
self.webshare_ssl_cert_path = self.app_dir+"/app_storage/ssl_cert.pem"
self.webshare_ssl_key_path = os.path.join(self.app_dir, "app_storage", "ssl_key.pem")
self.webshare_ssl_cert_path = os.path.join(self.app_dir, "app_storage", "ssl_cert.pem")
self.mqtt = None
self.mqtt_handle_lock = threading.Lock()
@ -319,9 +319,9 @@ class SidebandCore():
if RNS.vendor.platformutils.is_android():
if self.config["config_template"] != None:
try:
if not os.path.isfile(self.rns_configdir+"/config_template_invalid"):
if not os.path.isfile(os.path.join(self.rns_configdir, "config_template_invalid")):
if self.is_service:
with open(self.rns_configdir+"/config_template_invalid", "w") as invalidation_file:
with open(os.path.join(self.rns_configdir, "config_template_invalid"), "w") as invalidation_file:
invalidation_file.write("\n")
ct = self.config["config_template"]
@ -342,7 +342,7 @@ class SidebandCore():
# Initialise Reticulum configuration
if RNS.vendor.platformutils.get_platform() == "android":
try:
self.rns_configdir = self.app_dir+"/app_storage/reticulum"
self.rns_configdir = os.path.join(self.app_dir, "app_storage", "reticulum")
if not os.path.isdir(self.rns_configdir):
os.makedirs(self.rns_configdir)
@ -354,7 +354,7 @@ class SidebandCore():
RNS.log("Not enabling Reticulum Transport")
generated_config = self.config_template.replace("TRANSPORT_IS_ENABLED", "No")
config_file = open(self.rns_configdir+"/config", "wb")
config_file = open(os.path.join(self.rns_configdir, "config"), "wb")
config_file.write(generated_config.encode("utf-8"))
config_file.close()
@ -389,10 +389,10 @@ class SidebandCore():
app_entry_dir = os.path.expanduser("~/.local/share/applications")
icon_dir = os.path.expanduser("~/.local/share/icons/hicolor/512x512/apps")
de_filename = "io.unsigned.sideband.desktop"
de_source = self.asset_dir+"/"+de_filename
de_target = app_entry_dir+"/"+de_filename
icn_source = self.asset_dir+"/icon.png"
icn_target = icon_dir+"/io.unsigned.sideband.png"
de_source = os.path.join(self.asset_dir, de_filename)
de_target = os.path.join(app_entry_dir, de_filename)
icn_source = os.path.join(self.asset_dir, "icon.png")
icn_target = os.path.join(icon_dir, "io.unsigned.sideband.png")
if os.path.isdir(local_share_dir):
if not os.path.exists(app_entry_dir):
os.makedirs(app_entry_dir)
@ -435,13 +435,13 @@ class SidebandCore():
def clear_tmp_dir(self):
if os.path.isdir(self.tmp_dir):
for file in os.listdir(self.tmp_dir):
fpath = self.tmp_dir+"/"+file
fpath = os.path.join(self.tmp_dir, file)
os.unlink(fpath)
def clear_exports_dir(self):
if os.path.isdir(self.exports_dir):
for file in os.listdir(self.exports_dir):
fpath = self.exports_dir+"/"+file
fpath = os.path.join(self.exports_dir, file)
RNS.log("Clearing "+str(fpath))
os.unlink(fpath)
@ -637,7 +637,7 @@ class SidebandCore():
if not "classic_message_colors" in self.config: self.config["classic_message_colors"] = False
if not "display_style_in_contact_list" in self.config: self.config["display_style_in_contact_list"] = True
if not "lxm_limit_1mb" in self.config: self.config["lxm_limit_1mb"] = True
if not "hq_ptt" in self.config: self.config["hq_ptt"] = False
if not "hq_ptt" in self.config: self.config["hq_ptt"] = True
if not "trusted_markup_only" in self.config: self.config["trusted_markup_only"] = False
if not "compose_in_markdown" in self.config: self.config["compose_in_markdown"] = False
if not "confirm_calls" in self.config: self.config["confirm_calls"] = True
@ -811,7 +811,7 @@ class SidebandCore():
with open(self.config_path, "wb") as config_file: config_file.write(msgpack.packb(self.config))
self.saving_configuration = False
if RNS.vendor.platformutils.is_android():
boot_toggle_path = self.app_dir+"/app_storage/boot_toggle"
boot_toggle_path = os.path.join(self.app_dir, "app_storage", "boot_toggle")
boot_toggle_exists = os.path.isfile(boot_toggle_path)
if self.config["start_at_boot"] == True and not boot_toggle_exists:
with open(boot_toggle_path, "w") as f: f.write("true")
@ -942,12 +942,11 @@ class SidebandCore():
if notifications_permitted:
try:
if RNS.vendor.platformutils.get_platform() == "android":
if self.is_service:
self.owner_service.android_notification(title, content, group=group, context_id=context_id)
else:
plyer.notification.notify(title, content, notification_icon=self.notification_icon, context_override=None)
if self.is_service: self.owner_service.android_notification(title, content, group=group, context_id=context_id)
else: plyer.notification.notify(title, content, notification_icon=self.notification_icon, context_override=None)
else:
plyer.notification.notify(title, content, app_icon=self.icon_32)
if not RNS.vendor.platformutils.is_windows(): plyer.notification.notify(title, content, app_name="Sideband", app_icon=self.icon_48)
else: plyer.notification.notify(title, content, app_name="Sideband", app_icon=self.icon_windows)
except Exception as e:
RNS.log("An error occurred while posting a notification to the operating system: {e}", RNS.LOG_ERROR)
@ -4113,8 +4112,8 @@ class SidebandCore():
if RNS.vendor.platformutils.is_android():
if self.is_service:
if os.path.isfile(self.rns_configdir+"/config_template_invalid"):
os.unlink(self.rns_configdir+"/config_template_invalid")
if os.path.isfile(os.path.join(self.rns_configdir, "config_template_invalid")):
os.unlink(os.path.join(self.rns_configdir, "config_template_invalid"))
else:
pass
@ -5003,11 +5002,11 @@ class SidebandCore():
return
if audio_field[0] == LXMF.AM_OPUS_OGG:
temp_path = self.rec_cache+"/ptt_msg.ogg"
temp_path = os.path.join(self.rec_cache, "ptt_msg.ogg")
with open(temp_path, "wb") as af: af.write(self.last_msg_audio)
elif audio_field[0] >= LXMF.AM_CODEC2_700C and audio_field[0] <= LXMF.AM_CODEC2_3200:
temp_path = self.rec_cache+"/ptt_msg.ogg"
temp_path = os.path.join(self.rec_cache, "ptt_msg.ogg")
from sideband.audioproc import samples_to_ogg, decode_codec2, detect_codec2
target_rate = 48000

View file

@ -120,10 +120,9 @@ setuptools.setup(
"pillow>=10.2.0",
"qrcode",
"materialyoucolor>=2.0.7",
"ffpyplayer",
"sh",
"numpy>=2.0.0",
"lxst>=0.4.2",
"lxst>=0.4.4",
"mistune>=3.0.2",
"beautifulsoup4",
"pycodec2>=4.1.0",