Ejemplo n.º 1
0
    def get_tts_audio(self, message, language, options=None):
        """Load TTS from ResponsiveVoice."""
        if language is None:
            language = self._lang
        from responsive_voice import ResponsiveVoice

        # websession = async_get_clientsession(self.hass)
        try:
            engine = ResponsiveVoice()
            _LOGGER.error(message)
            data = engine.say(sentence=message,
                              gender=self._gender,
                              lang=self._lang)

        except HTTPException as ex:
            _LOGGER.error("Timeout for ResponsiveVoice speech")
            return None, None
        # try:
        #     with async_timeout.timeout(10, loop=self.hass.loop):
        #         engine = ResponsiveVoice()
        #         _LOGGER.error(message)
        #         data = engine.say(
        #             sentence=message, gender="self._gender", lang="self._lang"
        #             )

        #         if request.status != 200:
        #             _LOGGER.error("Error %d on load URL %s",
        #                           request.status, request.url)
        #             return None, None
        #         data += await request.read()

        # except (asyncio.TimeoutError, aiohttp.ClientError):
        #     _LOGGER.error("Timeout for ResponsiveVoice speech")
        #     return None, None
        return ('mp3', data)
Ejemplo n.º 2
0
    def get_tts_audio(self, message, language, options=None):
        """Load TTS from ResponsiveVoiceTTS."""

        engine = ResponsiveVoice()
        # from responsive_voice.voices import Ellen

        # ellen = Ellen()

        # result = ellen.say(message)
        print("message", message, "language", language, "pitch", self._pitch,
              "rate", self._speed, "vol", self._volume)

        result = engine.say(message,
                            language,
                            pitch=self._pitch,
                            rate=self._speed,
                            vol=self._volume)

        # result = engine.get_mp3(message, language, pitch=self._pitch,
        #                         rate=self._speed, vol=self._volume)

        # if options is None:
        #     result = engine.say(message, lang=language, pitch=self._pitch,
        #                         rate=self._speed, vol=self._volume)
        # else:
        #     speech_data = self._speech_conf_data.copy()
        #     for key, value in options.items():
        #         speech_data[_OPTIONS[key]] = value

        #     result = engine.say(message, language, 1, speech_data)

        print(result)

        if isinstance(result, dict):
            _LOGGER.error(
                "ResponsiveVoice TTS error-- err_no:%d; err_msg:%s; err_detail:%s",
                result["err_no"],
                result["err_msg"],
                result["err_detail"],
            )
            return None, None

        return self._codec, result
Ejemplo n.º 3
0
class BareSIP(Thread):
    def __init__(self,
                 user,
                 pwd,
                 gateway,
                 tts=None,
                 debug=False,
                 block=True,
                 audiodriver="alsa,default",
                 port=5060):
        self.debug = debug
        self.user = user
        self.pwd = pwd
        self.gateway = gateway

        #Learn the second one when it has to reasign a unique name
        #There is an in and an out client name
        self.jackNames = ['baresip']

        if tts:
            self.tts = tts
        else:
            try:
                from responsive_voice import ResponsiveVoice
                self.tts = ResponsiveVoice(gender=ResponsiveVoice.MALE)
            except ImportError:
                logging.exception(
                    "No responsive_voice module, some features will not work")
        self._login = "******".format(u=self.user,
                                               p=self.pwd,
                                               g=self.gateway)
        self._prev_output = ""
        self.running = False

        #Ready immediately, this is a localhost thing
        self.ready = True
        self.mic_muted = False
        self.abort = False
        self.current_call = None
        self._call_status = None
        self.audio = None
        self._ts = None

        self.jack_port = "baresip"

        cnfdir = os.path.join(tmpdir, "ScullerySIP" + str(port))
        self.cnfdir = cnfdir
        try:
            #Remove any existing
            shutil.rmtree(self.cnfdir)
        except:
            pass

        os.mkdir(os.path.join(tmpdir, "ScullerySIP" + str(port)))

        self.cnfdir = cnfdir
        #Using the template, create a configuration dir for
        #the baresip instance we are about to make.
        f = os.path.join(os.path.dirname(__file__), "baresip_template")

        drivers = "module\t\talsa.so"
        if 'jack' in audiodriver:
            drivers = "module\t\tjack.so"

        for i in os.listdir(f):
            with open(os.path.join(f, i)) as fd:
                x = fd.read()

            x = x.replace("USERNAME", user)
            x = x.replace("AUDIODRIVER", audiodriver)
            x = x.replace("PORT", str(port))
            x = x.replace("DRIVERS", str(drivers))

            with open(os.path.join(cnfdir, i), "w") as fd:
                fd.write(x)

        self.baresip = pexpect.spawn('baresip', ["-f", cnfdir])
        super().__init__()
        self.daemon = True

        self.start()
        if block:
            self.wait_until_ready()

    # properties
    @property
    def call_established(self):
        return self.call_status == "ESTABLISHED"

    @property
    def call_status(self):
        return self._call_status or "DISCONNECTED"

    # actions
    def do_command(self, action):
        if self.ready:
            action = str(action)
            self.baresip.sendline(action)
        else:
            LOG.warning(action + " not executed!")
            LOG.exception("NOT READY! please wait")

    def login(self):
        LOG.info("Adding account: " + self.user)
        self.baresip.sendline("/uanew " + self._login)

    def call(self, number):
        LOG.info("Dialling: " + number)
        self.do_command("/dial " + number)

    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 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 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 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 unmute_mic(self):
        if not self.call_established:
            LOG.error("Can not unmute microphone while not in a call")
            return
        if self.mic_muted:
            LOG.info("Unmuting mic")
            self.do_command("/mute")
        else:
            LOG.info("Mic already unmuted")

    def accept_call(self):
        self.do_command("/accept")
        status = "ESTABLISHED"
        self.handle_call_status(status)
        self._call_status = status

    def list_calls(self):
        self.do_command("/listcalls")

    def check_call_status(self):
        self.do_command("/callstat")
        sleep(0.1)
        return self.call_status

    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_dtmf(self, number):
        from opentone import ToneGenerator
        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(), "DTMF" + number + ".wav")
        ToneGenerator().dtmf_to_wave(number, dtmf)
        self.send_audio(dtmf)

    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 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")

    @staticmethod
    def convert_audio(input_file, outfile=None):
        from pydub import AudioSegment
        input_file = expanduser(input_file)
        sound = AudioSegment.from_file(input_file)
        sound += AudioSegment.silent(duration=500)
        # ensure minimum time
        # workaround baresip bug
        while sound.duration_seconds < 3:
            sound += AudioSegment.silent(duration=500)

        outfile = outfile or join(tempfile.gettempdir(), "pybaresip.wav")
        sound = sound.set_frame_rate(48000)
        sound = sound.set_channels(2)
        sound.export(outfile, format="wav")
        return outfile, sound.duration_seconds

    # this is played out loud over speakers
    def say(self, speech):
        if not self.call_established:
            LOG.warning("Speaking without an active call!")
        self.tts.say(speech, blocking=True)

    def play(self, audio_file, blocking=True):
        if not audio_file.endswith(".wav"):
            audio_file, duration = self.convert_audio(audio_file)
        self.audio = self._play_wav(audio_file, blocking=blocking)

    def stop_playing(self):
        if self.audio is not None:
            self.audio.kill()

    @staticmethod
    def _play_wav(wav_file, play_cmd="aplay %1", blocking=False):
        play_mp3_cmd = str(play_cmd).split(" ")
        for index, cmd in enumerate(play_mp3_cmd):
            if cmd == "%1":
                play_mp3_cmd[index] = wav_file
        if blocking:
            return subprocess.call(play_mp3_cmd)
        else:
            return subprocess.Popen(play_mp3_cmd)

    # events
    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_call_rejected(self, number):
        LOG.info("Rejected incoming call: " + number)

    def handle_call_timestamp(self, timestr):
        LOG.info("Call time: " + timestr)

    def handle_call_status(self, status):
        if status != self._call_status:
            LOG.debug("Call Status: " + status)

    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 handle_call_established(self):
        LOG.info("Call established")

    def handle_call_ended(self, reason):
        LOG.info("Call ended")
        LOG.debug("Reason: " + reason)

    def _handle_no_accounts(self):
        LOG.debug("No accounts setup")
        self.login()

    def handle_login_success(self):
        LOG.info("Logged in!")

    def handle_login_failure(self):
        LOG.error("Log in failed!")
        self.quit()

    def handle_ready(self):
        LOG.info("Ready for instructions")

    def handle_mic_muted(self):
        LOG.info("Microphone muted")

    def handle_mic_unmuted(self):
        LOG.info("Microphone unmuted")

    def handle_audio_stream_failure(self):
        LOG.debug("Aborting call, maybe we reached voicemail?")
        self.hang()

    def handle_error(self, error):
        LOG.error(error)
        if error == "failed to set audio-source (No such device)":
            self.handle_audio_stream_failure()

    def onJackAssigned(self, cname):
        if not cname in self.jackNames:
            self.jackNames.append(cname)
            #We only have 2, if there are more,
            #it means the default has been reassigned
            if len(self.jackNames) > 2:
                self.jackNames.pop(0)

    def on_audio_rtp(self, rtp):
        pass

    # event loop
    def run(self):
        self.running = True
        while self.running:
            try:
                out = self.baresip.readline().decode("utf-8")

                if out != self._prev_output:
                    out = out.strip()
                    if self.debug:
                        LOG.debug(out)
                    if "baresip is ready." in out:
                        self.handle_ready()
                    elif "account: No SIP accounts found" in out:
                        self._handle_no_accounts()
                    elif "All 1 useragent registered successfully!" in out:
                        self.ready = True
                        self.handle_login_success()

                    elif "ua: SIP register failed:" in out or\
                            "401 Unauthorized" in out or \
                            "Register: Destination address required" in out or\
                            "Register: Connection timed out" in out:
                        self.handle_error(out)
                        self.handle_login_failure()
                    elif "Incoming call from: " in out:
                        num = out.split("Incoming call from: ")[1].split(
                            " - (press 'a' to accept)")[0].strip()
                        self.current_call = num
                        self._call_status = "INCOMING"
                        self.handle_incoming_call(num)
                    elif "call: rejecting incoming call from " in out:
                        num = out.split("rejecting incoming call from "
                                        )[1].split(" ")[0].strip()
                        self.handle_call_rejected(num)
                    elif "call: SIP Progress: 180 Ringing" in out:
                        self.handle_call_ringing()
                        status = "RINGING"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "call: connecting to " in out:
                        n = out.split("call: connecting to '")[1].split("'")[0]
                        self.current_call = n
                        self.handle_call_start()
                        status = "OUTGOING"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "Call established:" in out:

                        status = "ESTABLISHED"
                        self.handle_call_status(status)
                        self._call_status = status
                        sleep(0.5)
                        self.handle_call_established()
                    elif "call: hold " in out:
                        n = out.split("call: hold ")[1]
                        status = "ON HOLD"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "Call with " in out and \
                            "terminated (duration: " in out:
                        status = "DISCONNECTED"
                        duration = out.split("terminated (duration: ")[1][:-1]
                        self.handle_call_status(status)
                        self._call_status = status
                        self.handle_call_timestamp(duration)
                        self.mic_muted = False
                    elif "call muted" in out:
                        self.mic_muted = True
                        self.handle_mic_muted()
                    elif "call un-muted" in out:
                        self.mic_muted = False
                        self.handle_mic_unmuted()
                    elif "session closed:" in out:
                        reason = out.split("session closed:")[1].strip()
                        status = "DISCONNECTED"
                        self.handle_call_status(status)
                        self._call_status = status
                        self.handle_call_ended(reason)
                        self.mic_muted = False
                    elif "(no active calls)" in out:
                        status = "DISCONNECTED"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "incoming rtp for 'audio' established, receiving from " in out:
                        rtp = out.split(
                            "stream: incoming rtp for 'audio' established, receiving from "
                        )
                        self.on_audio_rtp(rtp)

                    elif "===== Call debug " in out:
                        status = out.split("(")[1].split(")")[0]
                        self.handle_call_status(status)
                        self._call_status = status

                    elif 'jack' in out:
                        match = re.search(
                            r"jack: unique name \`(.*?)\' assigned", out)
                        if match:
                            self.onJackAssigned(match.groups(1)[0])

                    elif "--- List of active calls (1): ---" in \
                            self._prev_output:
                        if "ESTABLISHED" in out and self.current_call in out:
                            ts = out.split("ESTABLISHED")[0].split(
                                "[line 1]")[1].strip()
                            if ts != self._ts:
                                self._ts = ts
                                self.handle_call_timestamp(ts)

                    elif "failed to set audio-source (No such device)" in out:
                        error = "failed to set audio-source (No such device)"
                        self.handle_error(error)

                    self._prev_output = out
            except pexpect.exceptions.EOF:
                # baresip exited
                self.quit()
            except pexpect.exceptions.TIMEOUT:
                # nothing happened for a while
                pass
            except Exception:
                print(traceback.format_exc())

    def wait_until_ready(self):
        while not self.ready:
            sleep(0.1)
            if self.abort:
                return
Ejemplo n.º 4
0
from responsive_voice import ResponsiveVoice

engine = ResponsiveVoice()
engine.say("hello world")
engine.say("hello world", gender="male", lang="en-GB", rate=0.4)

file_path = engine.get_mp3(u"ola mundo", lang="pt-pt")
engine.play_mp3(file_path)
Ejemplo n.º 5
0
from responsive_voice import ResponsiveVoice

engine = ResponsiveVoice()
engine.say("hello world")
engine.say("hello world", gender=ResponsiveVoice.MALE, rate=0.45)

engine = ResponsiveVoice(lang=ResponsiveVoice.PORTUGUESE_BR)
file_path = engine.get_mp3(u"olá mundo")
engine.play_mp3(file_path)

from responsive_voice.voices import EnglishIndia, UKEnglishMale, \
    FallbackUKEnglishMale

india = EnglishIndia()
uk = UKEnglishMale()
uk2 = FallbackUKEnglishMale()
india.say("hello world")
uk.say("hello world")
uk2.say("hello world")
Ejemplo n.º 6
0
class BareSIP(Thread):
    def __init__(self, user, pwd, gateway, tts=None, debug=False, block=True):
        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')
        super().__init__()
        self.start()
        if block:
            self.wait_until_ready()

    # properties
    @property
    def call_established(self):
        return self.call_status == "ESTABLISHED"

    @property
    def call_status(self):
        return self._call_status or "DISCONNECTED"

    # actions
    def do_command(self, action):
        if self.ready:
            action = str(action)
            self.baresip.sendline(action)
        else:
            LOG.warning(action + " not executed!")
            LOG.error("NOT READY! please wait")

    def login(self):
        LOG.info("Adding account: " + self.user)
        self.baresip.sendline("/uanew " + self._login)

    def call(self, number):
        LOG.info("Dialling: " + number)
        self.do_command("/dial " + number)

    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 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 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 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 unmute_mic(self):
        if not self.call_established:
            LOG.error("Can not unmute microphone while not in a call")
            return
        if self.mic_muted:
            LOG.info("Unmuting mic")
            self.do_command("/mute")
        else:
            LOG.info("Mic already unmuted")

    def accept_call(self):
        self.do_command("/accept")
        status = "ESTABLISHED"
        self.handle_call_status(status)
        self._call_status = status

    def list_calls(self):
        self.do_command("/listcalls")

    def check_call_status(self):
        self.do_command("/callstat")
        sleep(0.1)
        return self.call_status

    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_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 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 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")

    @staticmethod
    def convert_audio(input_file, outfile=None):
        input_file = expanduser(input_file)
        sound = AudioSegment.from_file(input_file)
        sound += AudioSegment.silent(duration=500)
        # ensure minimum time
        # workaround baresip bug
        while sound.duration_seconds < 3:
            sound += AudioSegment.silent(duration=500)

        outfile = outfile or join(tempfile.gettempdir(), "pybaresip.wav")
        sound = sound.set_frame_rate(48000)
        sound = sound.set_channels(2)
        sound.export(outfile, format="wav")
        return outfile, sound.duration_seconds

    # this is played out loud over speakers
    def say(self, speech):
        if not self.call_established:
            LOG.warning("Speaking without an active call!")
        self.tts.say(speech, blocking=True)

    def play(self, audio_file, blocking=True):
        if not audio_file.endswith(".wav"):
            audio_file, duration = self.convert_audio(audio_file)
        self.audio = self._play_wav(audio_file, blocking=blocking)

    def stop_playing(self):
        if self.audio is not None:
            self.audio.kill()

    @staticmethod
    def _play_wav(wav_file, play_cmd="aplay %1", blocking=False):
        play_mp3_cmd = str(play_cmd).split(" ")
        for index, cmd in enumerate(play_mp3_cmd):
            if cmd == "%1":
                play_mp3_cmd[index] = wav_file
        if blocking:
            return subprocess.call(play_mp3_cmd)
        else:
            return subprocess.Popen(play_mp3_cmd)

    # events
    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_call_rejected(self, number):
        LOG.info("Rejected incoming call: " + number)

    def handle_call_timestamp(self, timestr):
        LOG.info("Call time: " + timestr)

    def handle_call_status(self, status):
        if status != self._call_status:
            LOG.debug("Call Status: " + status)

    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 handle_call_established(self):
        LOG.info("Call established")

    def handle_call_ended(self, reason):
        LOG.info("Call ended")
        LOG.debug("Reason: " + reason)

    def _handle_no_accounts(self):
        LOG.debug("No accounts setup")
        self.login()

    def handle_login_success(self):
        LOG.info("Logged in!")

    def handle_login_failure(self):
        LOG.error("Log in failed!")
        self.quit()

    def handle_ready(self):
        LOG.info("Ready for instructions")

    def handle_mic_muted(self):
        LOG.info("Microphone muted")

    def handle_mic_unmuted(self):
        LOG.info("Microphone unmuted")

    def handle_audio_stream_failure(self):
        LOG.debug("Aborting call, maybe we reached voicemail?")
        self.hang()

    def handle_error(self, error):
        LOG.error(error)
        if error == "failed to set audio-source (No such device)":
            self.handle_audio_stream_failure()

    # event loop
    def run(self):
        self.running = True
        while self.running:
            try:
                out = self.baresip.readline().decode("utf-8")

                if out != self._prev_output:
                    out = out.strip()
                    if self.debug:
                        LOG.debug(out)
                    if "baresip is ready." in out:
                        self.handle_ready()
                    elif "account: No SIP accounts found" in out:
                        self._handle_no_accounts()
                    elif "All 1 useragent registered successfully!" in out:
                        self.ready = True
                        self.handle_login_success()
                    elif "ua: SIP register failed:" in out or\
                            "401 Unauthorized" in out or \
                            "Register: Destination address required" in out or\
                            "Register: Connection timed out" in out:
                        self.handle_error(out)
                        self.handle_login_failure()
                    elif "Incoming call from: " in out:
                        num = out.split("Incoming call from: ")[1].split(
                            " - (press 'a' to accept)")[0].strip()
                        self.current_call = num
                        self._call_status = "INCOMING"
                        self.handle_incoming_call(num)
                    elif "call: rejecting incoming call from " in out:
                        num = out.split("rejecting incoming call from "
                                        )[1].split(" ")[0].strip()
                        self.handle_call_rejected(num)
                    elif "call: SIP Progress: 180 Ringing" in out:
                        self.handle_call_ringing()
                        status = "RINGING"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "call: connecting to " in out:
                        n = out.split("call: connecting to '")[1].split("'")[0]
                        self.current_call = n
                        self.handle_call_start()
                        status = "OUTGOING"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "Call established:" in out:

                        status = "ESTABLISHED"
                        self.handle_call_status(status)
                        self._call_status = status
                        sleep(0.5)
                        self.handle_call_established()
                    elif "call: hold " in out:
                        n = out.split("call: hold ")[1]
                        status = "ON HOLD"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "Call with " in out and \
                            "terminated (duration: " in out:
                        status = "DISCONNECTED"
                        duration = out.split("terminated (duration: ")[1][:-1]
                        self.handle_call_status(status)
                        self._call_status = status
                        self.handle_call_timestamp(duration)
                        self.mic_muted = False
                    elif "call muted" in out:
                        self.mic_muted = True
                        self.handle_mic_muted()
                    elif "call un-muted" in out:
                        self.mic_muted = False
                        self.handle_mic_unmuted()
                    elif "session closed:" in out:
                        reason = out.split("session closed:")[1].strip()
                        status = "DISCONNECTED"
                        self.handle_call_status(status)
                        self._call_status = status
                        self.handle_call_ended(reason)
                        self.mic_muted = False
                    elif "(no active calls)" in out:
                        status = "DISCONNECTED"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "===== Call debug " in out:
                        status = out.split("(")[1].split(")")[0]
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "--- List of active calls (1): ---" in \
                            self._prev_output:
                        if "ESTABLISHED" in out and self.current_call in out:
                            ts = out.split("ESTABLISHED")[0].split(
                                "[line 1]")[1].strip()
                            if ts != self._ts:
                                self._ts = ts
                                self.handle_call_timestamp(ts)
                    elif "failed to set audio-source (No such device)" in out:
                        error = "failed to set audio-source (No such device)"
                        self.handle_error(error)

                    self._prev_output = out
            except pexpect.exceptions.EOF:
                # baresip exited
                self.quit()
            except pexpect.exceptions.TIMEOUT:
                # nothing happened for a while
                pass

    def wait_until_ready(self):
        while not self.ready:
            sleep(0.1)
            if self.abort:
                return
Ejemplo n.º 7
0
class BareSIP(Thread):
    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()

    # properties
    @property
    def call_established(self):
        return self.call_status == "ESTABLISHED"

    @property
    def call_status(self):
        return self._call_status or "DISCONNECTED"

    # actions
    def do_command(self, action):
        if self.ready:
            action = str(action)
            self.baresip.sendline(action)
        else:
            LOG.warning(action + " not executed!")
            LOG.error("NOT READY! please wait")

    def login(self):
        LOG.info("Adding account: " + self.user)
        self.baresip.sendline("/uanew " + self._login)

    def call(self, number):
        LOG.info("Dialling: " + number)
        self.do_command("/dial " + number)

    def enable_recording(self):
        LOG.info("Enabling call recording")
        self.do_command("/insmod sndfile")

    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 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 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 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 unmute_mic(self):
        if not self.call_established:
            LOG.error("Can not unmute microphone while not in a call")
            return
        if self.mic_muted:
            LOG.info("Unmuting mic")
            self.do_command("/mute")
        else:
            LOG.info("Mic already unmuted")

    def accept_call(self):
        self.do_command("/accept")
        status = "ESTABLISHED"
        self.handle_call_status(status)
        self._call_status = status

    def list_calls(self):
        self.do_command("/listcalls")

    def check_call_status(self):
        self.do_command("/callstat")
        sleep(0.1)
        return self.call_status

    @staticmethod
    def get_contacts(config_dir=join(expanduser("~"), ".baresip")):
        """
        Read contacts and active_contact from config dir
        :param config_dir: baresip configration directory (default ~/.baresip)
        :return: (list) all_contacts(dict), current_contact(str)
        """

        with open(f"{config_dir}/current_contact") as cur:
            cur_con = cur.readline()
        with open(f"{config_dir}/contacts") as cons:
            raw = cons.readlines()
        contacts_list = []
        for line in raw:
            if not line.startswith("#") and line != "\n":
                contacts_list.append(line)
        contacts = {}
        for contact in contacts_list:
            name = contact.split('"', 2)[1]
            addr = contact.split('<', 1)[1].split('>', 1)[0]
            contacts[name] = addr
        return contacts, cur_con

    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 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 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 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")

    @staticmethod
    def convert_audio(input_file, outfile=None):
        input_file = expanduser(input_file)
        sound = AudioSegment.from_file(input_file)
        sound += AudioSegment.silent(duration=500)
        # ensure minimum time
        # workaround baresip bug
        while sound.duration_seconds < 3:
            sound += AudioSegment.silent(duration=500)

        outfile = outfile or join(tempfile.gettempdir(), "pybaresip.wav")
        sound = sound.set_frame_rate(48000)
        sound = sound.set_channels(2)
        sound.export(outfile, format="wav")
        return outfile, sound.duration_seconds

    # this is played out loud over speakers
    def say(self, speech):
        if not self.call_established:
            LOG.warning("Speaking without an active call!")
        self.tts.say(speech, blocking=True)

    def play(self, audio_file, blocking=True):
        if not audio_file.endswith(".wav"):
            audio_file, duration = self.convert_audio(audio_file)
        self.audio = self._play_wav(audio_file, blocking=blocking)

    def stop_playing(self):
        if self.audio is not None:
            self.audio.kill()

    @staticmethod
    def _play_wav(wav_file, play_cmd="aplay %1", blocking=False):
        play_mp3_cmd = str(play_cmd).split(" ")
        for index, cmd in enumerate(play_mp3_cmd):
            if cmd == "%1":
                play_mp3_cmd[index] = wav_file
        if blocking:
            return subprocess.call(play_mp3_cmd)
        else:
            return subprocess.Popen(play_mp3_cmd)

    # events
    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_call_rejected(self, number):
        LOG.info("Rejected incoming call: " + number)

    def handle_call_timestamp(self, timestr):
        LOG.info("Call time: " + timestr)

    def handle_call_status(self, status):
        if status != self._call_status:
            LOG.debug("Call Status: " + status)

    @staticmethod
    def handle_text_message(sender, text):
        LOG.info(f"rec'd: {text} | from: {sender}")

    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 handle_call_established(self):
        LOG.info("Call established")

    def handle_call_ended(self, reason):
        LOG.info("Call ended")
        LOG.debug("Reason: " + reason)

    def _handle_no_accounts(self):
        LOG.debug("No accounts setup")
        self.login()

    def handle_login_success(self):
        LOG.info("Logged in!")

    def handle_login_failure(self):
        LOG.error("Log in failed!")
        self.quit()

    def handle_ready(self):
        LOG.info("Ready for instructions")

    def handle_mic_muted(self):
        LOG.info("Microphone muted")

    def handle_mic_unmuted(self):
        LOG.info("Microphone unmuted")

    def handle_audio_stream_failure(self):
        LOG.debug("Aborting call, maybe we reached voicemail?")
        self.hang()

    def handle_error(self, error):
        LOG.error(error)
        if error == "failed to set audio-source (No such device)":
            self.handle_audio_stream_failure()

    # event loop
    def run(self):
        self.running = True
        while self.running:
            try:
                out = self.baresip.readline().decode("utf-8")

                if out != self._prev_output:
                    out = out.strip()
                    if self.debug:
                        LOG.debug(out)
                    if "baresip is ready." in out:
                        self.handle_ready()
                    elif "account: No SIP accounts found" in out:
                        self._handle_no_accounts()
                    elif "All 1 useragent registered successfully!" in out:
                        self.ready = True
                        self.handle_login_success()
                    elif "ua: SIP register failed:" in out or\
                            "401 Unauthorized" in out or \
                            "Register: Destination address required" in out or\
                            "Register: Connection timed out" in out or\
                            "403 Wrong Password" in out or\
                            "400 Bad From URI" in out:
                        self.handle_error(out)
                        self.handle_login_failure()
                    elif "Incoming call from: " in out:
                        num = out.split("Incoming call from: ")[1].split(
                            " - (press 'a' to accept)")[0].strip()
                        self.current_call = num
                        self._call_status = "INCOMING"
                        self.handle_incoming_call(num)
                    elif "call: rejecting incoming call from " in out:
                        num = out.split("rejecting incoming call from "
                                        )[1].split(" ")[0].strip()
                        self.handle_call_rejected(num)
                    elif "call: SIP Progress: 180 Ringing" in out:
                        self.handle_call_ringing()
                        status = "RINGING"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "call: connecting to " in out:
                        n = out.split("call: connecting to '")[1].split("'")[0]
                        self.current_call = n
                        self.handle_call_start()
                        status = "OUTGOING"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "Call established:" in out:

                        status = "ESTABLISHED"
                        self.handle_call_status(status)
                        self._call_status = status
                        sleep(0.5)
                        self.handle_call_established()
                    elif "call: hold " in out:
                        n = out.split("call: hold ")[1]
                        status = "ON HOLD"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "Call with " in out and \
                            "terminated (duration: " in out:
                        status = "DISCONNECTED"
                        duration = out.split("terminated (duration: ")[1][:-1]
                        self.handle_call_status(status)
                        self._call_status = status
                        self.handle_call_timestamp(duration)
                        self.mic_muted = False
                    elif "call muted" in out:
                        self.mic_muted = True
                        self.handle_mic_muted()
                    elif "call un-muted" in out:
                        self.mic_muted = False
                        self.handle_mic_unmuted()
                    elif "session closed:" in out:
                        reason = out.split("session closed:")[1].strip()
                        status = "DISCONNECTED"
                        self.handle_call_status(status)
                        self._call_status = status
                        self.handle_call_ended(reason)
                        self.mic_muted = False
                    elif "(no active calls)" in out:
                        status = "DISCONNECTED"
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "===== Call debug " in out:
                        status = out.split("(")[1].split(")")[0]
                        self.handle_call_status(status)
                        self._call_status = status
                    elif "--- List of active calls (1): ---" in \
                            self._prev_output:
                        if "ESTABLISHED" in out and self.current_call in out:
                            ts = out.split("ESTABLISHED")[0].split(
                                "[line 1]")[1].strip()
                            if ts != self._ts:
                                self._ts = ts
                                self.handle_call_timestamp(ts)
                    elif "failed to set audio-source (No such device)" in out:
                        error = "failed to set audio-source (No such device)"
                        self.handle_error(error)
                    elif "terminated by signal" in out or "ua: stop all" in out:
                        self.running = False
                    elif str(out).startswith("sip:") and str(out).endswith(
                            '"'):
                        _, sender, message = str(out).split(':', 2)
                        sender = f"sip:{sender}"
                        message = message.strip().strip('"')
                        self.handle_text_message(sender, message)

                    self._prev_output = out
            except pexpect.exceptions.EOF:
                # baresip exited
                self.running = False
            except pexpect.exceptions.TIMEOUT:
                # nothing happened for a while
                pass
            except KeyboardInterrupt:
                self.running = False

        self.quit()

    def wait_until_ready(self):
        while not self.ready:
            sleep(0.1)
            if self.abort:
                return
Ejemplo n.º 8
0
class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi('iwsss.ui', self)
        self.setDefaultUi()
        self.show()

    def setDefaultUi(self):
        self.version = self.findChild(QtWidgets.QLabel, 'version')
        self.version.setText("Mary 1.0.04")
        self.micButton = self.findChild(QtWidgets.QPushButton, 'micButton')
        self.Kelime_Label = self.findChild(QtWidgets.QLabel, 'Kelime_Label')
        self.Yanit_Label = self.findChild(QtWidgets.QLabel, 'Yanit_Label')
        self.Tip_Label = self.findChild(QtWidgets.QLabel, 'Tip_Label')
        self.Yanit_Layout = self.findChild(QtWidgets.QLayout,
                                           'horizontalLayout_2')
        self.Image_Label = self.findChild(QtWidgets.QLabel, 'Image_Label')
        self.sitelink1 = self.findChild(QtWidgets.QLabel, 'sitelink1')
        self.sitelink2 = self.findChild(QtWidgets.QLabel, 'sitelink2')
        self.sitelink3 = self.findChild(QtWidgets.QLabel, 'sitelink3')
        self.sitebaslik1 = self.findChild(QtWidgets.QLabel, 'sitebaslik1')
        self.sitebaslik2 = self.findChild(QtWidgets.QLabel, 'sitebaslik2')
        self.sitebaslik3 = self.findChild(QtWidgets.QLabel, 'sitebaslik3')
        self.sitebaslik1.setOpenExternalLinks(True)
        self.sitebaslik2.setOpenExternalLinks(True)
        self.sitebaslik3.setOpenExternalLinks(True)
        self.siteaciklama1 = self.findChild(QtWidgets.QLabel, 'siteaciklama1')
        self.siteaciklama2 = self.findChild(QtWidgets.QLabel, 'siteaciklama2')
        self.siteaciklama3 = self.findChild(QtWidgets.QLabel, 'siteaciklama3')
        self.web_sonuc1 = self.findChild(QtWidgets.QLayout, 'web_sonuc1')
        self.web_sonuc2 = self.findChild(QtWidgets.QLayout, 'web_sonuc2')
        self.web_sonuc3 = self.findChild(QtWidgets.QLayout, 'web_sonuc3')
        self.web_sonuc1.setSpacing(0)
        self.web_sonuc2.setSpacing(0)
        self.web_sonuc3.setSpacing(0)
        self.web_sonuc1.setContentsMargins(0, 0, 0, 0)
        self.web_sonuc2.setContentsMargins(0, 0, 0, 0)
        self.web_sonuc3.setContentsMargins(0, 0, 0, 0)
        self.micButton.clicked.connect(self.micButtonPressed)
        self.setWindowIcon(QtGui.QIcon('image/mary.png'))
        self.animasyon = False
        self.ttsIptal = False
        self.listenAktif = False
        self.micButtonClickable = True
        self.Image_Label.show()
        self.aktifThreadler = 0
        self.dosyakonumu = getcwd()
        self.soundPlayer = QtMultimedia.QMediaPlayer()
        self.soundPlayer.stateChanged.connect(self.soundPlayerState)
        #Tray icon
        self.tray_icon = QtWidgets.QSystemTrayIcon(self)
        self.tray_icon.setIcon(QtGui.QIcon("image/mary.png"))
        self.tray_icon.activated.connect(self.trayDoubleClick)
        show_action = QtWidgets.QAction("Göster", self)
        quit_action = QtWidgets.QAction("Çıkış yap", self)
        show_action.triggered.connect(self.show)
        quit_action.triggered.connect(self.closeApp)
        tray_menu = QtWidgets.QMenu()
        tray_menu.addAction(show_action)
        tray_menu.addAction(quit_action)
        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()

        for i in range(10):
            self.dosyakonumu = self.dosyakonumu.replace("\\", "/")
        i = "border-image: url('{}/image/background.png');".format(
            self.dosyakonumu)
        stylesheet = "#centralwidget{" + i + "}"
        self.setStyleSheet(stylesheet)
        self.micButton.setStyleSheet(
            "border-image: url('{}/image/mic_1.png');".format(
                self.dosyakonumu))
        self.yapilanislem = ""
        self.backgroundListen = True
        self.voiceEngine = ResponsiveVoice(lang=ResponsiveVoice.TURKISH,
                                           gender=ResponsiveVoice.FEMALE,
                                           pitch=0.52,
                                           rate=0.53,
                                           key="8FCWWns8",
                                           vol=0.97)
        threading.Thread(target=self.sesanimasyon, daemon=True).start()
        threading.Thread(target=self.background, daemon=True).start()
        self.db = Veritabani()
        if self.db.ad() == "":
            self.yapilanislem = "ilkacilis"
            threading.Thread(target=self.ilkCalistirma, daemon=True).start()

    def closeApp(self):
        self.hide()
        sys.exit()

    def closeEvent(self, event):
        event.ignore()
        self.hide()
        self.tray_icon.showMessage("Mary - Sesli asistan",
                                   "Sesli asistan simge durumuna küçültüldü",
                                   QtWidgets.QSystemTrayIcon.Information, 2000)

    def trayDoubleClick(self, reason):
        if reason == QtWidgets.QSystemTrayIcon.DoubleClick:
            self.show()

    def backgroundCallBack(self, audio):
        if self.backgroundListen:
            try:
                text = r.recognize_google(audio, language='tr-tr')
                liste = [
                    "Merih", "Melih", "Meri", "Mery", "MARIO", "Mary", "emery",
                    "h&m"
                ]
                for i in liste:
                    if i in text:
                        text = i.replace(i, "Mary")
                if "MARY" in text.upper():
                    self.notification = QtCore.QUrl.fromLocalFile(
                        "{}/notification.mp3".format(self.dosyakonumu))
                    self.soundPlayer.setMedia(
                        QtMultimedia.QMediaContent(self.notification))
                    self.soundPlayer.play()
                    self.listenAktif = True
                    self.ttsIptal = True
                    self.animasyon = True
                    self.backgroundListen = False
                    self.Tip_Label.setText("Dinleniyor")
                    self.micButton.setStyleSheet(
                        "border-image: url('{}/image/mic_2.png');".format(
                            self.dosyakonumu))
                    self.Tip_Label.setStyleSheet(
                        "background-color:#ff0000;color: rgb(255, 255, 255);")
                    self.show()
                    self.dinle = listenThread(parent=window)
                    self.dinle.start()
                    self.dinle.signal.connect(self.setUi)
                    self.backgroundListen = False
                else:
                    print(text)
            except sr.UnknownValueError:
                pass
            except sr.RequestError:
                pass
            else:
                print(text)
        SystemExit

    def background(self):
        while True:
            try:
                with sr.Microphone() as source:
                    audio = r.listen(source, timeout=2, phrase_time_limit=2)
                    threading.Thread(target=self.backgroundCallBack,
                                     args={audio}).start()
            except sr.WaitTimeoutError:
                pass

    def ilkCalistirma(self):
        self.micButton.setMaximumSize(0, 0)
        self.micButton.setMinimumSize(0, 0)
        self.backgroundListen = False
        self.Tip_Label.setText("")
        threading.Thread(
            target=self.setYanitLabel,
            args={"Hoşgeldin, Adım Mary. Ben senin sesli asistanınım."},
            daemon=True).start()
        self.voiceEngine.say(
            "Hoşgeldin, Adım Mary.\nBen senin sesli asistanınım.")
        threading.Thread(
            target=self.setYanitLabel,
            args={
                "Öncelikle adını öğrenebilir miyim?\nAdını söylemek için lütfen butona tıkla"
            },
            daemon=True).start()
        self.voiceEngine.say(
            "Öncelikle adını öğrenebilir miyim? Adını söylemek için lütfen butona tıkla"
        )
        self.micButton.setMaximumSize(80, 80)
        self.micButton.setMinimumSize(80, 80)
        self.Tip_Label.setText("Konuşmak için butona tıklayın")
        while True:
            time.sleep(0.1)
            if self.db.ad() != "":
                time.sleep(5)
                self.setYanitLabel("")
                self.Image_Label.show()
                self.Image_Label.setStyleSheet(
                    "border-image: url('{}/image/neler_yapabilirsin.png');".
                    format(self.dosyakonumu))
                self.Image_Label.setMaximumSize(630, 270)
                self.Image_Label.setMinimumSize(630, 270)
                self.voiceEngine.say(
                    f"Yapabileceklerimin bazıları şunlar {self.db.ad()}. Şimdi başlayabilirsin"
                )
                break
        sys.exit()

    def micButtonPressed(self):
        print("micButton Basıldı")
        if self.listenAktif:
            self.micButtonClickable = False
            self.micButton.setEnabled(False)
            self.ttsIptal = True
            self.listenAktif = False
            self.animasyon = False
            self.Tip_Label.setText("Konuşmak için butona tıklayın")
            self.Tip_Label.setStyleSheet("color: rgb(255, 255, 255);")
            self.micButton.setStyleSheet(
                "border-image: url('{}/image/mic_1.png');".format(
                    self.dosyakonumu))

            def i():
                time.sleep(2)
                self.micButtonClickable = True
                self.micButton.setEnabled(True)
                self.backgroundListen = True
                SystemExit

            threading.Thread(target=i, daemon=True).start()
        else:
            if self.micButtonClickable:
                self.listenAktif = True
                self.ttsIptal = True
                self.animasyon = True
                self.backgroundListen = False
                self.Tip_Label.setText("Dinleniyor")
                self.micButton.setStyleSheet(
                    "border-image: url('{}/image/mic_2.png');".format(
                        self.dosyakonumu))
                self.Tip_Label.setStyleSheet(
                    "background-color:#ff0000;color: rgb(255, 255, 255);")
                self.dinle = listenThread(parent=window)
                self.dinle.start()
                self.dinle.signal.connect(self.setUi)

    @staticmethod
    def sesanimasyon():
        def sound(indata, outdata, frames, time, status):
            volume_norm = norm(indata) * 20
            if window.animasyon:
                window.Tip_Label.setMinimumSize(70 + volume_norm, 0)

        while True:
            with sd.Stream(callback=sound):
                sd.sleep(1000000)

    def setYanitLabel(self, yazi, foto=False):
        self.Yanit_Label.setWordWrap(False)
        QtCore.QMetaObject.invokeMethod(self.Yanit_Label, "setText",
                                        QtCore.Qt.QueuedConnection,
                                        QtCore.Q_ARG(str, yazi))
        yaziBoyutu = QtGui.QFont()
        yaziBoyutu.setPointSize(22)
        if foto:
            self.Yanit_Label.setWordWrap(True)
            self.Yanit_Label.setAlignment(QtCore.Qt.AlignLeft)
        else:
            self.Yanit_Label.setAlignment(QtCore.Qt.AlignCenter)
        if len(yazi) <= 40:
            print("40'dan küçük")
            yaziBoyutu.setPointSize(22)
            self.Yanit_Label.setMaximumSize(1000, 99999)

        elif len(yazi) >= 40 and len(yazi) <= 50:
            print("40-50")
            yaziBoyutu.setPointSize(20)

        elif len(yazi) >= 50 and len(yazi) <= 60:
            print("50-60")
            yaziBoyutu.setPointSize(18)

        elif len(yazi) >= 60 and len(yazi) <= 70:
            print("60-70")
            yaziBoyutu.setPointSize(17)
            if foto:
                self.Yanit_Label.setMaximumSize(600, 99999)
            else:
                self.Yanit_Label.setMaximumSize(800, 99999)

        elif len(yazi) >= 70 and len(yazi) <= 130:
            print("70-130")
            if foto:
                self.Yanit_Label.setMaximumSize(800, 99999)
                self.Yanit_Label.setWordWrap(True)
                yaziBoyutu.setPointSize(18)
            else:
                self.Yanit_Label.setMaximumSize(1000, 99999)
                self.Yanit_Label.setWordWrap(True)
                yaziBoyutu.setPointSize(18)
        else:
            print(len(yazi))
            print("130 üstü")
            yaziBoyutu.setPointSize(14)
            if foto:
                self.Yanit_Label.setMaximumSize(400, 99999)
                self.Yanit_Label.setWordWrap(True)
            else:
                self.Yanit_Label.setMaximumSize(600, 99999)
                self.Yanit_Label.setWordWrap(True)
        self.Yanit_Label.setFont(yaziBoyutu)

    def labelClear(self):
        self.siteaciklama1.setText("")
        self.siteaciklama2.setText("")
        self.siteaciklama3.setText("")
        self.sitebaslik1.setText("")
        self.sitebaslik2.setText("")
        self.sitebaslik3.setText("")
        self.sitelink1.setText("")
        self.sitelink2.setText("")
        self.sitelink3.setText("")
        self.siteaciklama1.hide()
        self.siteaciklama2.hide()
        self.siteaciklama3.hide()
        self.sitebaslik1.hide()
        self.sitebaslik2.hide()
        self.sitebaslik3.hide()
        self.sitelink1.hide()
        self.sitelink2.hide()
        self.sitelink3.hide()
        self.web_sonuc1.setSpacing(0)
        self.web_sonuc2.setSpacing(0)
        self.web_sonuc3.setSpacing(0)
        self.web_sonuc1.setContentsMargins(0, 0, 0, 0)
        self.web_sonuc2.setContentsMargins(0, 0, 0, 0)
        self.web_sonuc3.setContentsMargins(0, 0, 0, 0)
        self.Image_Label.setAlignment(QtCore.Qt.AlignLeft)

    def setUi(self, komut):
        self.labelClear()
        if komut.yapilanislem == "neyapabilirsin":
            self.Image_Label.show()
            self.Image_Label.setStyleSheet(
                "border-image: url('{}/image/neler_yapabilirsin.png');".format(
                    self.dosyakonumu))
            self.Yanit_Label.setText("")
            self.Image_Label.setMinimumSize(630, 270)
            self.Image_Label.setMinimumSize(630, 270)
            self.Yanit_Layout.setSpacing(0)
            self.yapilanislem = ""
        elif komut.yapilanislem == "websiteSonuc":
            self.Image_Label.hide()
            self.sitebaslik1.setCursor(QtCore.Qt.PointingHandCursor)
            self.sitebaslik2.setCursor(QtCore.Qt.PointingHandCursor)
            self.sitebaslik3.setCursor(QtCore.Qt.PointingHandCursor)
            self.web_sonuc1.setContentsMargins(0, 15, 0, 15)
            self.web_sonuc2.setContentsMargins(0, 0, 0, 15)
            self.web_sonuc3.setContentsMargins(0, 0, 0, 15)
            self.web_sonuc1.setSpacing(3)
            self.web_sonuc2.setSpacing(3)
            self.web_sonuc3.setSpacing(3)
            self.siteaciklama1.show()
            self.siteaciklama2.show()
            self.siteaciklama3.show()
            self.sitebaslik1.show()
            self.sitebaslik2.show()
            self.sitebaslik3.show()
            self.sitelink1.show()
            self.sitelink2.show()
            self.sitelink3.show()
            self.Yanit_Label.setText("")
            self.sitelink1.setText(komut.linktext1)
            self.sitelink2.setText(komut.linktext2)
            self.sitelink3.setText(komut.linktext3)
            QtCore.QMetaObject.invokeMethod(
                self.sitebaslik1, "setText", QtCore.Qt.QueuedConnection,
                QtCore.Q_ARG(
                    str, "<a href='{}'><font color=white>{}</font></a>".format(
                        komut.link1, komut.linktext1)))
            QtCore.QMetaObject.invokeMethod(
                self.sitebaslik2, "setText", QtCore.Qt.QueuedConnection,
                QtCore.Q_ARG(
                    str, "<a href='{}'><font color=white>{}</font></a>".format(
                        komut.link2, komut.linktext2)))
            QtCore.QMetaObject.invokeMethod(
                self.sitebaslik3, "setText", QtCore.Qt.QueuedConnection,
                QtCore.Q_ARG(
                    str, "<a href='{}'><font color=white>{}</font></a>".format(
                        komut.link3, komut.linktext3)))
            self.siteaciklama1.setText(komut.aciklama1)
            self.siteaciklama2.setText(komut.aciklama2)
            self.siteaciklama3.setText(komut.aciklama3)
            self.yapilanislem = ""
        elif komut.foto:
            self.Image_Label.show()
            self.Image_Label.setStyleSheet(
                "border-image: url('{}/image/image.jpg');".format(
                    self.dosyakonumu))
            self.Image_Label.setMinimumSize(komut.width, komut.height)
            self.Image_Label.setMaximumSize(komut.width, komut.height)
            if komut.yapilanislem == "havadurumu":
                self.Yanit_Label.setAlignment(QtCore.Qt.AlignLeft)
                QtCore.QMetaObject.invokeMethod(
                    self.Yanit_Label, "setText", QtCore.Qt.QueuedConnection,
                    QtCore.Q_ARG(str, komut.labelText))
                self.Yanit_Layout.setSpacing(15)
                self.Image_Label.setAlignment(QtCore.Qt.AlignBottom)
                self.sitebaslik1.setText(komut.detay1)
                self.sitebaslik2.setText(komut.detay2)
                self.sitebaslik3.setText(komut.detay3)
                self.sitebaslik1.show()
                self.sitebaslik2.show()
                self.sitebaslik3.show()
                self.sitebaslik1.setCursor(QtCore.Qt.ArrowCursor)
                self.sitebaslik2.setCursor(QtCore.Qt.ArrowCursor)
                self.sitebaslik3.setCursor(QtCore.Qt.ArrowCursor)
                self.yapilanislem = ""
            else:
                self.Yanit_Layout.setSpacing(30)
                self.setYanitLabel(komut.labelText, foto=True)
        else:
            self.Image_Label.setStyleSheet("")
            self.Image_Label.setMinimumSize(0, 0)
            self.Image_Label.setMaximumSize(0, 0)
            self.Image_Label.hide()
            self.Yanit_Layout.setSpacing(6)
            self.setYanitLabel(komut.labelText)

    def soundPlayerState(self, state):
        if state == QtMultimedia.QMediaPlayer.PlayingState:
            pass
        elif state == QtMultimedia.QMediaPlayer.StoppedState:
            try:
                remove(self.soundPath)
                print("Text to speech bitti")
                self.ttsIptal = True
            except Exception as code:
                pass