def speak(self, speech): if not self.call_established: LOG.error("Speaking without an active call!") else: LOG.info("Sending TTS for " + speech) self.send_audio(self.tts.get_mp3(speech)) sleep(0.5)
def hang(self): if self.current_call: LOG.info("Hanging: " + self.current_call) self.do_command("/hangup") self.current_call = None self._call_status = None else: LOG.error("No active call to hang")
def mute_mic(self): if not self.call_established: LOG.error("Can not mute microphone while not in a call") return if not self.mic_muted: LOG.info("Muting mic") self.do_command("/mute") else: LOG.info("Mic already muted")
def send_dtmf(self, number): number = str(number) for n in number: if n not in "0123456789": LOG.error("invalid dtmf tone") return LOG.info("Sending dtmf tones for " + number) dtmf = join(tempfile.gettempdir(), number + ".wav") ToneGenerator().dtmf_to_wave(number, dtmf) self.send_audio(dtmf)
def quit(self): LOG.info("Exiting") if self.running: if self.current_call: self.hang() self.baresip.sendline("/quit") self.running = False self.current_call = None self._call_status = None self.abort = True
def send_audio(self, wav_file): if not self.call_established: LOG.error("Can't send audio without an active call!") return wav_file, duration = self.convert_audio(wav_file) # send audio stream LOG.info("transmitting audio") self.do_command("/ausrc aufile," + wav_file) # wait till playback ends sleep(duration - 0.5) # avoid baresip exiting self.do_command("/ausrc alsa,default")
def quit(self): if self.updated_config: LOG.info("restoring original config") with open(join(self.config_path, "config"), "w") as f: f.write(self._original_config) LOG.info("Exiting") if self.running: if self.current_call: self.hang() self.baresip.sendline("/quit") self.running = False self.current_call = None self._call_status = None self.abort = True self.baresip.close() self.baresip.kill(signal.SIGKILL)
def handle_incoming_call(self, number): LOG.info("Incoming call: " + number) if self.call_established: LOG.info("already in a call, rejecting") sleep(0.1) self.do_command("b") else: LOG.info("default behaviour, rejecting call") sleep(0.1) self.do_command("b")
def handle_login_success(self): LOG.info("Logged in!")
def handle_call_ended(self, reason): LOG.info("Call ended") LOG.debug("Reason: " + reason)
def handle_call_established(self): LOG.info("Call established")
def handle_text_message(sender, text): LOG.info(f"rec'd: {text} | from: {sender}")
def resume(self): if self.current_call: LOG.info("Resuming " + self.current_call) self.do_command("/resume") else: LOG.error("No active call to resume")
def login(self): LOG.info("Adding account: " + self.user) self.baresip.sendline("/uanew " + self._login)
def __init__(self, user, pwd, gateway, tts=None, debug=False, block=True, config_path=None, sounds_path=None): config_path = config_path or join("~", ".baresipy") self.config_path = expanduser(config_path) if not isdir(self.config_path): makedirs(self.config_path) if isfile(join(self.config_path, "config")): with open(join(self.config_path, "config"), "r") as f: self.config = f.read() LOG.info("config loaded from " + self.config_path + "/config") self.updated_config = False else: self.config = baresipy.config.DEFAULT self.updated_config = True self._original_config = str(self.config) if sounds_path is not None and "#audio_path" in self.config: self.updated_config = True if sounds_path is False: # sounds disabled self.config = self.config.replace( "#audio_path /usr/share/baresip", "audio_path /dont/load") elif isdir(sounds_path): self.config = self.config.replace( "#audio_path /usr/share/baresip", "audio_path " + sounds_path) if self.updated_config: with open(join(self.config_path, "config.bak"), "w") as f: f.write(self._original_config) LOG.info("saving config") with open(join(self.config_path, "config"), "w") as f: f.write(self.config) self.debug = debug self.user = user self.pwd = pwd self.gateway = gateway if tts: self.tts = tts else: self.tts = ResponsiveVoice(gender=ResponsiveVoice.MALE) self._login = "******".format(u=self.user, p=self.pwd, g=self.gateway) self._prev_output = "" self.running = False self.ready = False self.mic_muted = False self.abort = False self.current_call = None self._call_status = None self.audio = None self._ts = None self.baresip = pexpect.spawn('baresip -f ' + self.config_path) super().__init__() self.start() if block: self.wait_until_ready()
def handle_ready(self): LOG.info("Ready for instructions")
def handle_mic_unmuted(self): LOG.info("Microphone unmuted")
def handle_call_rejected(self, number): LOG.info("Rejected incoming call: " + number)
def call(self, number): LOG.info("Dialling: " + number) self.do_command("/dial " + number)
def handle_call_timestamp(self, timestr): LOG.info("Call time: " + timestr)
def hold(self): if self.current_call: LOG.info("Holding: " + self.current_call) self.do_command("/hold") else: LOG.error("No active call to hold")
def handle_call_start(self): number = self.current_call LOG.info("Calling: " + number)
def handle_call_ringing(self): number = self.current_call LOG.info(number + " is Ringing")
def enable_recording(self): LOG.info("Enabling call recording") self.do_command("/insmod sndfile")