mirror of
https://github.com/markqvist/Sideband.git
synced 2025-12-12 15:25:40 -05:00
Implemented voice call support on Android
This commit is contained in:
parent
7d0c9e8c4d
commit
cf0d64a746
3 changed files with 119 additions and 42 deletions
|
|
@ -1385,9 +1385,8 @@ class SidebandApp(MDApp):
|
||||||
dialog = MDDialog(
|
dialog = MDDialog(
|
||||||
title="Error",
|
title="Error",
|
||||||
text=info_text,
|
text=info_text,
|
||||||
buttons=[ ok_button ],
|
buttons=[ ok_button ])
|
||||||
# elevation=0,
|
|
||||||
)
|
|
||||||
def dl_ok(s):
|
def dl_ok(s):
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
self.quit_action(s)
|
self.quit_action(s)
|
||||||
|
|
@ -1434,10 +1433,16 @@ class SidebandApp(MDApp):
|
||||||
self.hw_error_dialog.open()
|
self.hw_error_dialog.open()
|
||||||
self.hw_error_dialog.is_open = True
|
self.hw_error_dialog.is_open = True
|
||||||
|
|
||||||
|
if RNS.vendor.platformutils.is_android():
|
||||||
|
service_voice_running = self.sideband.service_voice_running()
|
||||||
|
if service_voice_running: self.sideband.voice_running = True
|
||||||
|
else: self.sideband.voice_running = False
|
||||||
|
|
||||||
incoming_call = self.sideband.getstate("voice.incoming_call")
|
incoming_call = self.sideband.getstate("voice.incoming_call")
|
||||||
if incoming_call:
|
if incoming_call:
|
||||||
self.sideband.setstate("voice.incoming_call", None)
|
self.sideband.setstate("voice.incoming_call", None)
|
||||||
toast(f"Call from {incoming_call}", duration=7)
|
if RNS.vendor.platformutils.is_android(): toast(f"Call from {incoming_call}")
|
||||||
|
else: toast(f"Call from {incoming_call}", duration=7)
|
||||||
|
|
||||||
if self.root.ids.screen_manager.current == "messages_screen":
|
if self.root.ids.screen_manager.current == "messages_screen":
|
||||||
self.messages_view.update()
|
self.messages_view.update()
|
||||||
|
|
@ -3521,10 +3526,8 @@ class SidebandApp(MDApp):
|
||||||
self.sideband.config["voice_enabled"] = self.settings_screen.ids.settings_voice_enabled.active
|
self.sideband.config["voice_enabled"] = self.settings_screen.ids.settings_voice_enabled.active
|
||||||
self.sideband.save_configuration()
|
self.sideband.save_configuration()
|
||||||
|
|
||||||
if self.sideband.config["voice_enabled"] == True:
|
if self.sideband.config["voice_enabled"] == True: self.sideband.start_voice()
|
||||||
self.sideband.start_voice()
|
else: self.sideband.stop_voice()
|
||||||
else:
|
|
||||||
self.sideband.stop_voice()
|
|
||||||
|
|
||||||
def save_print_command(sender=None, event=None):
|
def save_print_command(sender=None, event=None):
|
||||||
if not sender.focus:
|
if not sender.focus:
|
||||||
|
|
@ -5784,7 +5787,9 @@ class SidebandApp(MDApp):
|
||||||
|
|
||||||
def voice_answer_action(self, sender=None):
|
def voice_answer_action(self, sender=None):
|
||||||
if self.sideband.voice_running:
|
if self.sideband.voice_running:
|
||||||
if self.sideband.telephone.is_ringing: self.sideband.telephone.answer()
|
if self.sideband.telephone.is_ringing:
|
||||||
|
self.sideband.telephone.answer()
|
||||||
|
toast("Call answered")
|
||||||
|
|
||||||
def voice_reject_action(self, sender=None):
|
def voice_reject_action(self, sender=None):
|
||||||
if self.sideband.voice_running:
|
if self.sideband.voice_running:
|
||||||
|
|
|
||||||
|
|
@ -1767,6 +1767,9 @@ class SidebandCore():
|
||||||
def gui_conversation(self):
|
def gui_conversation(self):
|
||||||
return self.getstate("app.active_conversation")
|
return self.getstate("app.active_conversation")
|
||||||
|
|
||||||
|
def service_voice_running(self):
|
||||||
|
return self.getstate("voice.running")
|
||||||
|
|
||||||
def setstate(self, prop, val):
|
def setstate(self, prop, val):
|
||||||
with self.state_lock:
|
with self.state_lock:
|
||||||
if not self.service_stopped:
|
if not self.service_stopped:
|
||||||
|
|
@ -2083,16 +2086,6 @@ class SidebandCore():
|
||||||
elif "set_ui_recording" in call:
|
elif "set_ui_recording" in call:
|
||||||
self.service_rpc_set_ui_recording(call["set_ui_recording"])
|
self.service_rpc_set_ui_recording(call["set_ui_recording"])
|
||||||
connection.send(True)
|
connection.send(True)
|
||||||
elif "get_plugins_info" in call:
|
|
||||||
connection.send(self._get_plugins_info())
|
|
||||||
elif "get_destination_establishment_rate" in call:
|
|
||||||
connection.send(self._get_destination_establishment_rate(call["get_destination_establishment_rate"]))
|
|
||||||
elif "get_destination_mtu" in call:
|
|
||||||
connection.send(self._get_destination_mtu(call["get_destination_mtu"]))
|
|
||||||
elif "get_destination_edr" in call:
|
|
||||||
connection.send(self._get_destination_edr(call["get_destination_edr"]))
|
|
||||||
elif "get_destination_lmd" in call:
|
|
||||||
connection.send(self._get_destination_lmd(call["get_destination_lmd"]))
|
|
||||||
elif "send_message" in call:
|
elif "send_message" in call:
|
||||||
args = call["send_message"]
|
args = call["send_message"]
|
||||||
send_result = self.send_message(
|
send_result = self.send_message(
|
||||||
|
|
@ -2128,25 +2121,32 @@ class SidebandCore():
|
||||||
is_authorized_telemetry_request=args["is_authorized_telemetry_request"]
|
is_authorized_telemetry_request=args["is_authorized_telemetry_request"]
|
||||||
)
|
)
|
||||||
connection.send(send_result)
|
connection.send(send_result)
|
||||||
elif "get_lxm_progress" in call:
|
elif "get_plugins_info" in call: connection.send(self._get_plugins_info())
|
||||||
args = call["get_lxm_progress"]
|
elif "get_destination_establishment_rate" in call: connection.send(self._get_destination_establishment_rate(call["get_destination_establishment_rate"]))
|
||||||
connection.send(self.get_lxm_progress(args["lxm_hash"]))
|
elif "get_destination_mtu" in call: connection.send(self._get_destination_mtu(call["get_destination_mtu"]))
|
||||||
elif "get_lxm_stamp_cost" in call:
|
elif "get_destination_edr" in call: connection.send(self._get_destination_edr(call["get_destination_edr"]))
|
||||||
args = call["get_lxm_stamp_cost"]
|
elif "get_destination_lmd" in call: connection.send(self._get_destination_lmd(call["get_destination_lmd"]))
|
||||||
connection.send(self.get_lxm_stamp_cost(args["lxm_hash"]))
|
elif "get_lxm_progress" in call: connection.send(self.get_lxm_progress(call["get_lxm_progress"]["lxm_hash"]))
|
||||||
elif "get_lxm_propagation_cost" in call:
|
elif "get_lxm_stamp_cost" in call: connection.send(self.get_lxm_stamp_cost(call["get_lxm_stamp_cost"]["lxm_hash"]))
|
||||||
args = call["get_lxm_propagation_cost"]
|
elif "get_lxm_propagation_cost" in call: connection.send(self.get_lxm_propagation_cost(call["get_lxm_propagation_cost"]["lxm_hash"]))
|
||||||
connection.send(self.get_lxm_propagation_cost(args["lxm_hash"]))
|
elif "is_tracking" in call: connection.send(self.is_tracking(call["is_tracking"]))
|
||||||
elif "is_tracking" in call:
|
elif "start_tracking" in call: connection.send(self.start_tracking(object_addr=call["start_tracking"]["object_addr"], interval=args["interval"], duration=args["duration"]))
|
||||||
connection.send(self.is_tracking(call["is_tracking"]))
|
elif "stop_tracking" in call: connection.send(self.stop_tracking(object_addr=call["stop_tracking"]["object_addr"]))
|
||||||
elif "start_tracking" in call:
|
elif "get_service_log" in call: connection.send(self.get_service_log())
|
||||||
args = call["start_tracking"]
|
elif "start_voice" in call: connection.send(self.start_voice())
|
||||||
connection.send(self.start_tracking(object_addr=args["object_addr"], interval=args["interval"], duration=args["duration"]))
|
elif "stop_voice" in call: connection.send(self.stop_voice())
|
||||||
elif "stop_tracking" in call:
|
elif "telephone_is_available" in call: connection.send(self.telephone.is_available) if self.telephone else False
|
||||||
args = call["stop_tracking"]
|
elif "telephone_is_in_call" in call: connection.send(self.telephone.is_in_call) if self.telephone else False
|
||||||
connection.send(self.stop_tracking(object_addr=args["object_addr"]))
|
elif "telephone_call_is_connecting" in call: connection.send(self.telephone.call_is_connecting) if self.telephone else False
|
||||||
elif "get_service_log" in call:
|
elif "telephone_is_ringing" in call: connection.send(self.telephone.is_ringing) if self.telephone else False
|
||||||
connection.send(self.get_service_log())
|
elif "telephone_caller_info" in call: connection.send(self.telephone.caller.hash) if self.telephone and self.telephone.caller else None
|
||||||
|
elif "telephone_set_busy" in call: connection.send(self.telephone.set_busy(call["telephone_set_busy"])) if self.telephone else False
|
||||||
|
elif "telephone_dial" in call: connection.send(self.telephone.dial(call["telephone_dial"])) if self.telephone else False
|
||||||
|
elif "telephone_hangup" in call: connection.send(self.telephone.hangup()) if self.telephone else False
|
||||||
|
elif "telephone_answer" in call: connection.send(self.telephone.answer()) if self.telephone else False
|
||||||
|
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
|
||||||
else:
|
else:
|
||||||
connection.send(None)
|
connection.send(None)
|
||||||
|
|
||||||
|
|
@ -3896,8 +3896,14 @@ class SidebandCore():
|
||||||
|
|
||||||
if self.is_standalone or self.is_client:
|
if self.is_standalone or self.is_client:
|
||||||
if self.config["telemetry_enabled"]: self.run_telemetry()
|
if self.config["telemetry_enabled"]: self.run_telemetry()
|
||||||
if self.config["voice_enabled"]: self.start_voice()
|
if self.config["voice_enabled"]:
|
||||||
|
if not RNS.vendor.platformutils.is_android(): self.start_voice()
|
||||||
|
else:
|
||||||
|
from .voice import ReticulumTelephoneProxy
|
||||||
|
self.telephone = ReticulumTelephoneProxy(owner=self)
|
||||||
|
|
||||||
elif self.is_service:
|
elif self.is_service:
|
||||||
|
if self.config["voice_enabled"]: self.start_voice()
|
||||||
self.run_service_telemetry()
|
self.run_service_telemetry()
|
||||||
|
|
||||||
def __add_localinterface(self, delay=None):
|
def __add_localinterface(self, delay=None):
|
||||||
|
|
@ -5501,22 +5507,40 @@ class SidebandCore():
|
||||||
if not self.reticulum.is_connected_to_shared_instance:
|
if not self.reticulum.is_connected_to_shared_instance:
|
||||||
RNS.Transport.detach_interfaces()
|
RNS.Transport.detach_interfaces()
|
||||||
|
|
||||||
def start_voice(self):
|
def _start_voice(self):
|
||||||
try:
|
try:
|
||||||
if not self.voice_running:
|
if not self.voice_running:
|
||||||
RNS.log("Starting voice service", RNS.LOG_DEBUG)
|
RNS.log("Starting voice service", RNS.LOG_DEBUG)
|
||||||
self.voice_running = True
|
self.voice_running = True
|
||||||
|
self.setstate("voice.running", self.voice_running)
|
||||||
from .voice import ReticulumTelephone
|
from .voice import ReticulumTelephone
|
||||||
self.telephone = ReticulumTelephone(self.identity, owner=self, speaker=self.config["voice_output"], microphone=self.config["voice_input"], ringer=self.config["voice_ringer"])
|
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")
|
ringtone_path = os.path.join(self.asset_dir, "audio", "notifications", "soft1.opus")
|
||||||
self.telephone.set_ringtone(ringtone_path)
|
self.telephone.set_ringtone(ringtone_path)
|
||||||
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.voice_running = False
|
self.voice_running = False
|
||||||
RNS.log(f"An error occurred while starting voice services, the contained exception was: {e}", RNS.LOG_ERROR)
|
RNS.log(f"An error occurred while starting voice services, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.trace_exception(e)
|
RNS.trace_exception(e)
|
||||||
|
return False
|
||||||
|
|
||||||
def stop_voice(self):
|
def start_voice(self):
|
||||||
|
if not RNS.vendor.platformutils.is_android(): return self._start_voice()
|
||||||
|
else:
|
||||||
|
if self.is_service: return self._start_voice()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.service_rpc_request({"start_voice": True}):
|
||||||
|
from .voice import ReticulumTelephoneProxy
|
||||||
|
self.telephone = ReticulumTelephoneProxy(owner=self)
|
||||||
|
self.voice_running = True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Error while starting voice service over RPC: "+str(e), RNS.LOG_DEBUG)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _stop_voice(self):
|
||||||
try:
|
try:
|
||||||
if self.voice_running:
|
if self.voice_running:
|
||||||
RNS.log("Stopping voice service", RNS.LOG_DEBUG)
|
RNS.log("Stopping voice service", RNS.LOG_DEBUG)
|
||||||
|
|
@ -5526,10 +5550,27 @@ class SidebandCore():
|
||||||
|
|
||||||
self.telephone = None
|
self.telephone = None
|
||||||
self.voice_running = False
|
self.voice_running = False
|
||||||
|
self.setstate("voice.running", self.voice_running)
|
||||||
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log(f"An error occurred while stopping voice services, the contained exception was: {e}", RNS.LOG_ERROR)
|
RNS.log(f"An error occurred while stopping voice services, the contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
RNS.trace_exception(e)
|
RNS.trace_exception(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def stop_voice(self):
|
||||||
|
if not RNS.vendor.platformutils.is_android(): return self._stop_voice()
|
||||||
|
else:
|
||||||
|
if self.is_service: return self._stop_voice()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if self.service_rpc_request({"stop_voice": True}):
|
||||||
|
self.telephone = None
|
||||||
|
self.voice_running = False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Error while stopping voice service over RPC: "+str(e), RNS.LOG_DEBUG)
|
||||||
|
return False
|
||||||
|
|
||||||
def incoming_call(self, remote_identity):
|
def incoming_call(self, remote_identity):
|
||||||
display_name = self.voice_display_name(remote_identity.hash)
|
display_name = self.voice_display_name(remote_identity.hash)
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ class ReticulumTelephone():
|
||||||
self.aliases = {}
|
self.aliases = {}
|
||||||
self.names = {}
|
self.names = {}
|
||||||
|
|
||||||
self.telephone = Telephone(self.identity, ring_time=self.RING_TIME, wait_time=self.WAIT_TIME)
|
self.telephone = Telephone(self.identity, ring_time=self.RING_TIME, wait_time=self.WAIT_TIME)
|
||||||
self.telephone.set_ringing_callback(self.ringing)
|
self.telephone.set_ringing_callback(self.ringing)
|
||||||
self.telephone.set_established_callback(self.call_established)
|
self.telephone.set_established_callback(self.call_established)
|
||||||
self.telephone.set_ended_callback(self.call_ended)
|
self.telephone.set_ended_callback(self.call_ended)
|
||||||
|
|
@ -169,3 +169,34 @@ class ReticulumTelephone():
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
class CallerProxy():
|
||||||
|
def __init__(self, hash=None):
|
||||||
|
self.hash = hash
|
||||||
|
|
||||||
|
class ReticulumTelephoneProxy():
|
||||||
|
PATH_TIME = ReticulumTelephone.PATH_TIME
|
||||||
|
def __init__(self, owner=None): self.owner = owner
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_available(self): return self.owner.service_rpc_request({"telephone_is_available": True })
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_in_call(self): return self.owner.service_rpc_request({"telephone_is_in_call": True })
|
||||||
|
|
||||||
|
@property
|
||||||
|
def call_is_connecting(self): return self.owner.service_rpc_request({"telephone_call_is_connecting": True })
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_ringing(self): return self.owner.service_rpc_request({"telephone_is_ringing": True })
|
||||||
|
|
||||||
|
@property
|
||||||
|
def caller(self): return CallerProxy(hash=self.owner.service_rpc_request({"telephone_caller_info": True }))
|
||||||
|
|
||||||
|
def set_busy(self, busy): return self.owner.service_rpc_request({"telephone_set_busy": busy })
|
||||||
|
def dial(self, dial_target): return self.owner.service_rpc_request({"telephone_dial": dial_target })
|
||||||
|
def hangup(self): return self.owner.service_rpc_request({"telephone_hangup": True })
|
||||||
|
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 })
|
||||||
Loading…
Add table
Add a link
Reference in a new issue