tts_text_in, tts_child_text_in = multiprocessing.Pipe()
    # used to send TTS text

    command_connections = (vio_commands, vad_commands, asr_commands, tts_commands)

    non_command_connections = (vio_record, vio_child_record,
                               vio_play, vio_child_play,
                               vad_audio_out, vad_child_audio_out,
                               asr_hypotheses_out, asr_child_hypotheses,
                               tts_text_in, tts_child_text_in)

    close_event = multiprocessing.Event()

    vio = VoipIO(cfg, vio_child_commands, vio_child_record, vio_child_play, close_event)
    vad = VAD(cfg, vad_child_commands, vio_record, vad_child_audio_out, close_event)
    asr = ASR(cfg, asr_child_commands, vad_audio_out, asr_child_hypotheses, close_event)
    tts = TTS(cfg, tts_child_commands, tts_child_text_in, vio_play, close_event)

    vio.start()
    vad.start()
    asr.start()
    tts.start()

    # Actively call a number configured.
    #vio_commands.send(Command('make_call(destination="\'Bejcek Eduard\' <sip:4366@SECRET:5066>")', 'HUB', 'VoipIO'))
    #vio_commands.send(Command('make_call(destination="sip:4366@SECRET:5066")', 'HUB', 'VoipIO'))
    #vio_commands.send(Command('make_call(destination="4366")', 'HUB', 'VoipIO'))
    #vio_commands.send(Command('make_call(destination="155")', 'HUB', 'VoipIO'))

    count = 0
    max_count = 50000
Example #2
0
File: ahub.py Project: tkraut/alex
    def run(self):
        try:
            # AIO pipes
            # used to send commands to VoipIO
            aio_commands, aio_child_commands = multiprocessing.Pipe()
            # I read from this connection recorded audio
            aio_record, aio_child_record = multiprocessing.Pipe()
            # I write in audio to be played
            aio_play, aio_child_play = multiprocessing.Pipe()

            # VAD pipes
            # used to send commands to VAD
            vad_commands, vad_child_commands = multiprocessing.Pipe()
            # used to read output audio from VAD
            vad_audio_out, vad_child_audio_out = multiprocessing.Pipe()

            # ASR pipes
            # used to send commands to ASR
            asr_commands, asr_child_commands = multiprocessing.Pipe()
            # used to read ASR hypotheses
            asr_hypotheses_out, asr_child_hypotheses = multiprocessing.Pipe()

            # SLU pipes
            # used to send commands to SLU
            slu_commands, slu_child_commands = multiprocessing.Pipe()
            # used to read SLU hypotheses
            slu_hypotheses_out, slu_child_hypotheses = multiprocessing.Pipe()

            # DM pipes
            # used to send commands to DM
            dm_commands, dm_child_commands = multiprocessing.Pipe()
            # used to read DM actions
            dm_actions_out, dm_child_actions = multiprocessing.Pipe()

            # NLG pipes
            # used to send commands to NLG
            nlg_commands, nlg_child_commands = multiprocessing.Pipe()
            # used to read NLG output
            nlg_text_out, nlg_child_text = multiprocessing.Pipe()

            # TTS pipes
            # used to send commands to TTS
            tts_commands, tts_child_commands = multiprocessing.Pipe()

            command_connections = [
                aio_commands, vad_commands, asr_commands, slu_commands,
                dm_commands, nlg_commands, tts_commands
            ]

            non_command_connections = [
                aio_record, aio_child_record, aio_play, aio_child_play,
                vad_audio_out, vad_child_audio_out, asr_hypotheses_out,
                asr_child_hypotheses, slu_hypotheses_out, slu_child_hypotheses,
                dm_actions_out, dm_child_actions, nlg_text_out, nlg_child_text
            ]

            close_event = multiprocessing.Event()

            # create the hub components
            aio = AudioIO(self.cfg, aio_child_commands, aio_child_record,
                          aio_child_play, close_event)
            vad = VAD(self.cfg, vad_child_commands, aio_record,
                      vad_child_audio_out, close_event)
            asr = ASR(self.cfg, asr_child_commands, vad_audio_out,
                      asr_child_hypotheses, close_event)
            slu = SLU(self.cfg, slu_child_commands, asr_hypotheses_out,
                      slu_child_hypotheses, close_event)
            dm = DM(self.cfg, dm_child_commands, slu_hypotheses_out,
                    dm_child_actions, close_event)
            nlg = NLG(self.cfg, nlg_child_commands, dm_actions_out,
                      nlg_child_text, close_event)
            tts = TTS(self.cfg, tts_child_commands, nlg_text_out, aio_play,
                      close_event)

            # start the hub components
            aio.start()
            vad.start()
            asr.start()
            slu.start()
            dm.start()
            nlg.start()
            tts.start()

            self.cfg['Logging']['session_logger'].set_close_event(
                self.close_event)
            self.cfg['Logging']['session_logger'].set_cfg(self.cfg)
            self.cfg['Logging']['session_logger'].start()

            # init the system
            call_start = 0
            call_back_time = -1
            call_back_uri = None

            s_voice_activity = False
            s_last_voice_activity_time = 0
            u_voice_activity = False
            u_last_voice_activity_time = 0

            s_last_dm_activity_time = 0

            hangup = False

            call_start = time.time()

            self.cfg['Logging']['system_logger'].session_start("@LOCAL_CALL")
            self.cfg['Logging']['system_logger'].session_system_log(
                'config = ' + str(self.cfg))

            self.cfg['Logging']['session_logger'].session_start(
                self.cfg['Logging']['system_logger'].get_session_dir_name())
            self.cfg['Logging']['session_logger'].config('config = ' +
                                                         str(self.cfg))
            self.cfg['Logging']['session_logger'].header(
                self.cfg['Logging']["system_name"],
                self.cfg['Logging']["version"])
            self.cfg['Logging']['session_logger'].input_source("aio")

            while 1:
                # Check the close event.
                if self.close_event.is_set():
                    print 'Received close event in: %s' % multiprocessing.current_process(
                    ).name
                    return

                time.sleep(self.cfg['Hub']['main_loop_sleep_time'])

                if call_back_time != -1 and call_back_time < time.time():
                    aio_commands.send(Command('make_call(destination="%s")' % \
                                              call_back_uri, 'HUB', 'AIO'))
                    call_back_time = -1
                    call_back_uri = None

                if vad_commands.poll():
                    command = vad_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "speech_start":
                            u_voice_activity = True
                        if command.parsed['__name__'] == "speech_end":
                            u_voice_activity = False
                            u_last_voice_activity_time = time.time()

                if asr_commands.poll():
                    command = asr_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                if slu_commands.poll():
                    command = slu_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                if dm_commands.poll():
                    command = dm_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "hangup":
                            # prepare for ending the call
                            hangup = True

                        if command.parsed['__name__'] == "dm_da_generated":
                            # record the time of the last system generated dialogue act
                            s_last_dm_activity_time = time.time()

                if nlg_commands.poll():
                    command = nlg_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                if tts_commands.poll():
                    command = tts_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                current_time = time.time()

            # stop processes
            aio_commands.send(Command('stop()', 'HUB', 'AIO'))
            vad_commands.send(Command('stop()', 'HUB', 'VAD'))
            asr_commands.send(Command('stop()', 'HUB', 'ASR'))
            slu_commands.send(Command('stop()', 'HUB', 'SLU'))
            dm_commands.send(Command('stop()', 'HUB', 'DM'))
            nlg_commands.send(Command('stop()', 'HUB', 'NLG'))
            tts_commands.send(Command('stop()', 'HUB', 'TTS'))

            # clean connections
            for c in command_connections:
                while c.poll():
                    c.recv()

            for c in non_command_connections:
                while c.poll():
                    c.recv()

            # wait for processes to stop
            # do not join, because in case of exception the join will not be successful
            # aio.join()
            # vad.join()
            # asr.join()
            # slu.join()
            # dm.join()
            # nlg.join()
            # tts.join()
            #cfg['Logging']['session_logger'].join()

        except KeyboardInterrupt:
            print 'KeyboardInterrupt exception in: %s' % multiprocessing.current_process(
            ).name
            self.close_event.set()
            return
        except:
            self.cfg['Logging']['system_logger'].exception(
                'Uncaught exception in AHUB process.')
            self.close_event.set()
            raise

        print 'Exiting: %s. Setting close event' % multiprocessing.current_process(
        ).name
        self.close_event.set()
Example #3
0
    def run(self):
        try:
            cfg = self.cfg

            vio_commands, vio_child_commands = multiprocessing.Pipe(
            )  # used to send commands to VoipIO
            vio_record, vio_child_record = multiprocessing.Pipe(
            )  # I read from this connection recorded audio
            vio_play, vio_child_play = multiprocessing.Pipe(
            )  # I write in audio to be played

            vad_commands, vad_child_commands = multiprocessing.Pipe(
            )  # used to send commands to VAD
            vad_audio_out, vad_child_audio_out = multiprocessing.Pipe(
            )  # used to read output audio from VAD

            asr_commands, asr_child_commands = multiprocessing.Pipe(
            )  # used to send commands to ASR
            asr_hypotheses_out, asr_child_hypotheses = multiprocessing.Pipe(
            )  # used to read ASR hypotheses

            slu_commands, slu_child_commands = multiprocessing.Pipe(
            )  # used to send commands to SLU
            slu_hypotheses_out, slu_child_hypotheses = multiprocessing.Pipe(
            )  # used to read SLU hypotheses

            dm_commands, dm_child_commands = multiprocessing.Pipe(
            )  # used to send commands to DM
            dm_actions_out, dm_child_actions = multiprocessing.Pipe(
            )  # used to read DM actions

            nlg_commands, nlg_child_commands = multiprocessing.Pipe(
            )  # used to send commands to NLG
            nlg_text_out, nlg_child_text = multiprocessing.Pipe(
            )  # used to read NLG output

            tts_commands, tts_child_commands = multiprocessing.Pipe(
            )  # used to send commands to TTS

            command_connections = [
                vio_commands, vad_commands, asr_commands, slu_commands,
                dm_commands, nlg_commands, tts_commands
            ]

            non_command_connections = [
                vio_record, vio_child_record, vio_play, vio_child_play,
                vad_audio_out, vad_child_audio_out, asr_hypotheses_out,
                asr_child_hypotheses, slu_hypotheses_out, slu_child_hypotheses,
                dm_actions_out, dm_child_actions, nlg_text_out, nlg_child_text
            ]

            vio = self.voice_io_cls(self.cfg, vio_child_commands,
                                    vio_child_record, vio_child_play,
                                    self.close_event)
            vad = VAD(self.cfg, vad_child_commands, vio_record,
                      vad_child_audio_out, self.close_event)
            asr = ASR(self.cfg, asr_child_commands, vad_audio_out,
                      asr_child_hypotheses, self.close_event)
            slu = SLU(self.cfg, slu_child_commands, asr_hypotheses_out,
                      slu_child_hypotheses, self.close_event)
            dm = DM(self.cfg, dm_child_commands, slu_hypotheses_out,
                    dm_child_actions, self.close_event)
            nlg = NLG(self.cfg, nlg_child_commands, dm_actions_out,
                      nlg_child_text, self.close_event)
            tts = TTS(self.cfg, tts_child_commands, nlg_text_out, vio_play,
                      self.close_event)

            vio.start()
            vad.start()
            asr.start()
            slu.start()
            dm.start()
            nlg.start()
            tts.start()

            self.write_pid_file([['vio', vio.pid], ['vad', vad.pid],
                                 ['asr', asr.pid], ['slu', slu.pid],
                                 ['dm', dm.pid], ['nlg', nlg.pid],
                                 ['tts', tts.pid]])

            cfg['Logging']['session_logger'].set_close_event(self.close_event)
            cfg['Logging']['session_logger'].set_cfg(cfg)
            cfg['Logging']['session_logger'].start()
            cfg['Logging']['session_logger'].cancel_join_thread()

            # init the system
            call_start = 0
            call_back_time = -1
            call_back_uri = None
            number_of_turns = -1

            s_voice_activity = False
            s_last_voice_activity_time = 0
            u_voice_activity = False
            u_last_voice_activity_time = 0

            s_last_dm_activity_time = 0

            u_last_input_timeout = 0

            call_connected = False
            hangup = False
            ncalls = 0

            outstanding_nlg_da = None

            call_db = CallDB(self.cfg, self.cfg[self.hubname]['call_db'],
                             self.cfg[self.hubname]['period'])
            #call_db.log()

            while 1:
                # Check the close event.
                if self.close_event.is_set():
                    print 'Received close event in: %s' % multiprocessing.current_process(
                    ).name
                    return

                time.sleep(self.cfg['Hub']['main_loop_sleep_time'])

                if call_back_time != -1 and call_back_time < time.time():
                    vio_commands.send(
                        Command('make_call(destination="%s")' % call_back_uri,
                                'HUB', 'VoipIO'))
                    call_back_time = -1
                    call_back_uri = None

                # read all messages
                if vio_commands.poll():
                    command = vio_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):

                        if command.parsed['__name__'] == "incoming_call":
                            self.cfg['Logging']['system_logger'].session_start(
                                command.parsed['remote_uri'])
                            self.cfg['Logging'][
                                'session_logger'].session_start(
                                    self.cfg['Logging']
                                    ['system_logger'].get_session_dir_name())

                            self.cfg['Logging'][
                                'system_logger'].session_system_log(
                                    'config = ' + unicode(self.cfg))
                            self.cfg['Logging']['session_logger'].config(
                                'config = ' + unicode(self.cfg))
                            self.cfg['Logging']['session_logger'].header(
                                self.cfg['Logging']["system_name"],
                                self.cfg['Logging']["version"])
                            self.cfg['Logging']['session_logger'].input_source(
                                "voip")

                            self.cfg['Analytics'].start_session(
                                command.parsed['remote_uri'])
                            self.cfg['Analytics'].track_event(
                                'vhub', 'incoming_call',
                                command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "rejected_call":
                            call_back_time = time.time() + self.cfg['VoipHub'][
                                'wait_time_before_calling_back']
                            call_back_uri = command.parsed['remote_uri']

                            self.cfg['Analytics'].track_event(
                                'vhub', 'rejected_call',
                                command.parsed['remote_uri'])

                        if command.parsed[
                                '__name__'] == "rejected_call_from_blacklisted_uri":
                            remote_uri = command.parsed['remote_uri']

                            num_all_calls, total_time, last_period_num_calls, last_period_total_time, last_period_num_short_calls = call_db.get_uri_stats(
                                remote_uri)

                            m = []
                            m.append('')
                            m.append('=' * 120)
                            m.append(
                                'Rejected incoming call from blacklisted URI: %s'
                                % remote_uri)
                            m.append('-' * 120)
                            m.append('Total calls:                  %d' %
                                     num_all_calls)
                            m.append('Total time (min):             %0.1f' %
                                     (total_time / 60.0, ))
                            m.append('Last period short calls:      %d' %
                                     last_period_num_short_calls)
                            m.append('Last period total calls:      %d' %
                                     last_period_num_calls)
                            m.append('Last period total time (min): %0.1f' %
                                     (last_period_total_time / 60.0, ))
                            m.append('=' * 120)
                            m.append('')
                            self.cfg['Logging']['system_logger'].info(
                                '\n'.join(m))

                            self.cfg['Analytics'].track_event(
                                'vhub', 'rejected_call_from_blacklisted_uri',
                                command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "call_connecting":
                            self.cfg['Analytics'].track_event(
                                'vhub', 'call_connecting',
                                command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "call_confirmed":
                            remote_uri = command.parsed['remote_uri']
                            num_all_calls, total_time, last_period_num_calls, last_period_total_time, last_period_num_short_calls = call_db.get_uri_stats(
                                remote_uri)

                            m = []
                            m.append('')
                            m.append('=' * 120)
                            m.append('Incoming call from :          %s' %
                                     remote_uri)
                            m.append('-' * 120)
                            m.append('Total calls:                  %d' %
                                     num_all_calls)
                            m.append('Total time (min):             %0.1f' %
                                     (total_time / 60.0, ))
                            m.append('Last period short calls:      %d' %
                                     last_period_num_short_calls)
                            m.append('Last period total calls:      %d' %
                                     last_period_num_calls)
                            m.append('Last period total time (min): %0.1f' %
                                     (last_period_total_time / 60.0, ))
                            m.append('-' * 120)

                            if last_period_num_calls > self.cfg[self.hubname]['last_period_max_num_calls'] or \
                                    last_period_total_time > self.cfg[self.hubname]['last_period_max_total_time'] or \
                                    last_period_num_short_calls > self.cfg[self.hubname]['last_period_max_num_short_calls'] :
                                # prepare for ending the call
                                call_connected = True

                                call_start = time.time()
                                number_of_turns = -1
                                s_voice_activity = True
                                s_last_voice_activity_time = time.time()
                                u_voice_activity = False
                                u_last_voice_activity_time = time.time()
                                u_last_input_timeout = time.time()
                                hangup = True

                                self.cfg['Logging']['session_logger'].turn(
                                    "system")
                                tts_commands.send(
                                    Command(
                                        'synthesize(text="%s",log="true")' %
                                        self.cfg[self.hubname]
                                        ['limit_reached_message'], 'HUB',
                                        'TTS'))
                                vio_commands.send(
                                    Command(
                                        'black_list(remote_uri="%s",expire="%d")'
                                        % (remote_uri, time.time() + self.cfg[
                                            self.hubname]['blacklist_for']),
                                        'HUB', 'VoipIO'))
                                m.append('CALL REJECTED')
                            else:
                                # init the system
                                call_connected = True

                                call_start = time.time()
                                number_of_turns = 0

                                s_voice_activity = False
                                s_last_voice_activity_time = 0
                                u_voice_activity = False
                                u_last_voice_activity_time = time.time()
                                u_last_input_timeout = time.time()
                                hangup = False

                                dm_commands.send(
                                    Command('new_dialogue()', 'HUB', 'DM'))
                                m.append('CALL ACCEPTED')

                            m.append('=' * 120)
                            m.append('')
                            self.cfg['Logging']['system_logger'].info(
                                '\n'.join(m))

                            call_db.track_confirmed_call(remote_uri)
                            self.cfg['Analytics'].track_event(
                                'vhub', 'call_confirmed',
                                command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "call_disconnected":
                            # flush vio, when flushed, vad will be flushed
                            vio_commands.send(
                                Command('flush()', 'HUB', 'VoipIO'))

                            self.cfg['Logging']['system_logger'].session_end()
                            self.cfg['Logging']['session_logger'].session_end()

                            remote_uri = command.parsed['remote_uri']
                            call_db.track_disconnected_call(remote_uri)

                            call_connected = False
                            number_of_turns = -1
                            ncalls += 1

                            self.cfg['Analytics'].track_event(
                                'vhub', 'call_disconnected',
                                command.parsed['remote_uri'])

                            dm_commands.send(
                                Command('prepare_new_dialogue()', 'HUB', 'DM'))

                        if command.parsed[
                                '__name__'] == "play_utterance_start":
                            s_voice_activity = True
                            s_last_voice_activity_time = time.time()

                        if command.parsed['__name__'] == "play_utterance_end":
                            s_voice_activity = False
                            s_last_voice_activity_time = time.time()

                        if command.parsed['__name__'] == "flushed":
                            # flush vad, when flushed, asr will be flushed
                            vad_commands.send(Command('flush()', 'HUB', 'VAD'))

                        if command.parsed['__name__'] == "flushed_out":
                            # process the outstanding DA if necessary
                            if outstanding_nlg_da:
                                nlg_commands.send(
                                    DMDA(outstanding_nlg_da, 'HUB', 'NLG'))
                                outstanding_nlg_da = None

                if vad_commands.poll():
                    command = vad_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "speech_start":
                            u_voice_activity = True

                            # interrupt the talking system
                            # this will be replaced with pausing the system when the necessary extension of pjsip
                            # is implemented
                            if s_voice_activity and s_last_voice_activity_time + 0.02 < current_time:
                                # if the system is still talking then flush the output
                                self.cfg['Logging']['session_logger'].barge_in(
                                    "system")

                                # when a user barge in into the output, all the output pipe line
                                # must be flushed
                                nlg_commands.send(
                                    Command('flush()', 'HUB', 'NLG'))
                                s_voice_activity = False
                                s_last_voice_activity_time = time.time()

                        if command.parsed['__name__'] == "speech_end":
                            u_voice_activity = False
                            u_last_voice_activity_time = time.time()

                        if command.parsed['__name__'] == "flushed":
                            # flush asr, when flushed, slu will be flushed
                            asr_commands.send(Command('flush()', 'HUB', 'ASR'))

                if asr_commands.poll():
                    command = asr_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, ASRHyp):
                        vio_commands.send(command)
                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "flushed":
                            # flush slu, when flushed, dm will be flushed
                            slu_commands.send(Command('flush()', 'HUB', 'SLU'))

                if slu_commands.poll():
                    command = slu_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "flushed":
                            # flush dm, when flushed, nlg will be flushed
                            dm_commands.send(Command('flush()', 'HUB', 'DM'))
                            dm_commands.send(
                                Command('end_dialogue()', 'HUB', 'DM'))

                if dm_commands.poll():
                    command = dm_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "hangup":
                            # prepare for ending the call
                            hangup = True
                            self.cfg['Analytics'].track_event(
                                'vhub', 'system_hangup')

                        if command.parsed['__name__'] == "flushed":
                            # flush nlg, when flushed, tts will be flushed
                            nlg_commands.send(Command('flush()', 'HUB', 'NLG'))

                    elif isinstance(command, DMDA):
                        # record the time of the last system generated dialogue act
                        s_last_dm_activity_time = time.time()
                        number_of_turns += 1

                        if command.da != "silence()":
                            # if the DM generated non-silence dialogue act, then continue in processing it

                            if s_voice_activity and s_last_voice_activity_time + 0.02 < current_time:
                                # if the system is still talking then flush the output
                                self.cfg['Logging']['session_logger'].barge_in(
                                    "system")

                                # when a user barge in into the output, all the output pipe line
                                # must be flushed
                                nlg_commands.send(
                                    Command('flush()', 'HUB', 'NLG'))
                                s_voice_activity = False
                                s_last_voice_activity_time = time.time()

                                # the DA will be send when all the following components are flushed
                                outstanding_nlg_da = command.da

                            else:
                                nlg_commands.send(
                                    DMDA(command.da, "HUB", "NLG"))

                if nlg_commands.poll():
                    command = nlg_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, TTSText):
                        vio_commands.send(command)
                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "flushed":
                            # flush tts, when flushed, vio will be flushed
                            tts_commands.send(Command('flush()', 'HUB', 'TTS'))

                if tts_commands.poll():
                    command = tts_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "flushed":
                            # flush vio_out
                            vio_commands.send(
                                Command('flush_out()', 'HUB', 'VIO'))

                current_time = time.time()

                s_diff = current_time - s_last_voice_activity_time
                u_diff = current_time - u_last_voice_activity_time
                t_diff = current_time - u_last_input_timeout
                timeout = self.cfg['DM']['input_timeout']

                if call_connected and \
                    not s_voice_activity and not u_voice_activity and \
                    s_diff > timeout and \
                    u_diff > timeout and \
                    t_diff > timeout:

                    u_last_input_timeout = time.time()
                    print 'timeout!!!!!', time.time()
                    dm_commands.send(
                        Command(
                            'timeout(silence_time="%0.3f")' %
                            min(s_diff, u_diff), 'HUB', 'DM'))

                if hangup and s_last_dm_activity_time + 2.0 < current_time and \
                    s_voice_activity == False and s_last_voice_activity_time + 2.0 < current_time:
                    # we are ready to hangup only when all voice activity is finished
                    hangup = False
                    vio_commands.send(Command('hangup()', 'HUB', 'VoipIO'))

                if number_of_turns != -1 and current_time - call_start > self.cfg[self.hubname]['hard_time_limit'] or \
                    number_of_turns > self.cfg[self.hubname]['hard_turn_limit']:
                    # hard hangup due to the hard limits
                    call_start = 0
                    number_of_turns = -1
                    vio_commands.send(Command('hangup()', 'HUB', 'VoipIO'))

                if self.ncalls != 0 and not call_connected and s_last_dm_activity_time + 5.0 < current_time and ncalls >= self.ncalls:
                    break

            # stop processes
            vio_commands.send(Command('stop()', 'HUB', 'VoipIO'))
            vad_commands.send(Command('stop()', 'HUB', 'VAD'))
            asr_commands.send(Command('stop()', 'HUB', 'ASR'))
            slu_commands.send(Command('stop()', 'HUB', 'SLU'))
            dm_commands.send(Command('stop()', 'HUB', 'DM'))
            nlg_commands.send(Command('stop()', 'HUB', 'NLG'))
            tts_commands.send(Command('stop()', 'HUB', 'TTS'))

            # clean connections
            for c in command_connections:
                while c.poll():
                    c.recv()

            for c in non_command_connections:
                while c.poll():
                    c.recv()

            # wait for processes to stop
            # do not join, because in case of exception the join will not be successful
            # vio.join()
            # vad.join()
            # asr.join()
            # slu.join()
            # dm.join()
            # nlg.join()
            # tts.join()
            #cfg['Logging']['session_logger'].join()

        except KeyboardInterrupt:
            print 'KeyboardInterrupt exception in: %s' % multiprocessing.current_process(
            ).name
            self.close_event.set()
            return
        except:
            self.cfg['Logging']['system_logger'].exception(
                'Uncaught exception in VHUB process.')
            self.close_event.set()
            raise

        print 'Exiting: %s. Setting close event' % multiprocessing.current_process(
        ).name
        self.close_event.set()
Example #4
0
    def run(self):
        # AIO pipes
        # used to send commands to VoipIO
        aio_commands, aio_child_commands = multiprocessing.Pipe()
        # I read from this connection recorded audio
        aio_record, aio_child_record = multiprocessing.Pipe()
        # I write in audio to be played
        aio_play, aio_child_play = multiprocessing.Pipe()

        # VAD pipes
        # used to send commands to VAD
        vad_commands, vad_child_commands = multiprocessing.Pipe()
        # used to read output audio from VAD
        vad_audio_out, vad_child_audio_out = multiprocessing.Pipe()

        # ASR pipes
        # used to send commands to ASR
        asr_commands, asr_child_commands = multiprocessing.Pipe()
        # used to read ASR hypotheses
        asr_hypotheses_out, asr_child_hypotheses = multiprocessing.Pipe()

        # SLU pipes
        # used to send commands to SLU
        slu_commands, slu_child_commands = multiprocessing.Pipe()
        # used to read SLU hypotheses
        slu_hypotheses_out, slu_child_hypotheses = multiprocessing.Pipe()

        # DM pipes
        # used to send commands to DM
        dm_commands, dm_child_commands = multiprocessing.Pipe()
        # used to read DM actions
        dm_actions_out, dm_child_actions = multiprocessing.Pipe()

        # NLG pipes
        # used to send commands to NLG
        nlg_commands, nlg_child_commands = multiprocessing.Pipe()
        # used to read NLG output
        nlg_text_out, nlg_child_text = multiprocessing.Pipe()

        # TTS pipes
        # used to send commands to TTS
        tts_commands, tts_child_commands = multiprocessing.Pipe()

        command_connections = [
            aio_commands, vad_commands, asr_commands, slu_commands,
            dm_commands, nlg_commands, tts_commands
        ]

        non_command_connections = [
            aio_record, aio_child_record, aio_play, aio_child_play,
            vad_audio_out, vad_child_audio_out, asr_hypotheses_out,
            asr_child_hypotheses, slu_hypotheses_out, slu_child_hypotheses,
            dm_actions_out, dm_child_actions, nlg_text_out, nlg_child_text
        ]

        # create the hub components
        close_event = multiprocessing.Event()
        aio = WebIO(self.cfg, aio_child_commands, aio_child_record,
                    aio_child_play, close_event)
        vad = VAD(self.cfg, vad_child_commands, aio_record,
                  vad_child_audio_out, close_event)
        asr = ASR(self.cfg, asr_child_commands, vad_audio_out,
                  asr_child_hypotheses, close_event)
        slu = SLU(self.cfg, slu_child_commands, asr_hypotheses_out,
                  slu_child_hypotheses, close_event)
        dm = DM(self.cfg, dm_child_commands, slu_hypotheses_out,
                dm_child_actions, close_event)
        nlg = NLG(self.cfg, nlg_child_commands, dm_actions_out, nlg_child_text,
                  close_event)
        tts = TTS(self.cfg, tts_child_commands, nlg_text_out, aio_play,
                  close_event)

        # start the hub components
        aio.start()
        vad.start()
        asr.start()
        slu.start()
        dm.start()
        nlg.start()
        tts.start()

        # init the system
        call_back_time = -1
        call_back_uri = None
        call_start = time.time()

        self.cfg['Logging']['system_logger'].session_start("@LOCAL_CALL")
        self.cfg['Logging']['system_logger'].session_system_log('config = ' +
                                                                str(self.cfg))

        self.cfg['Logging']['session_logger'].session_start(
            self.cfg['Logging']['system_logger'].get_session_dir_name())
        self.cfg['Logging']['session_logger'].config('config = ' +
                                                     str(self.cfg))
        self.cfg['Logging']['session_logger'].header(
            self.cfg['Logging']["system_name"], self.cfg['Logging']["version"])
        self.cfg['Logging']['session_logger'].input_source("aio")

        while 1:
            time.sleep(self.cfg['Hub']['main_loop_sleep_time'])

            if call_back_time != -1 and call_back_time < time.time():
                aio_commands.send(
                    Command('make_call(destination="%s")' % call_back_uri,
                            'HUB', 'AIO'))
                call_back_time = -1
                call_back_uri = None

            if vad_commands.poll():
                command = vad_commands.recv()
                self.cfg['Logging']['system_logger'].info(command)

                if isinstance(command, Command):
                    if command.parsed['__name__'] == "speech_start":
                        pass
                    if command.parsed['__name__'] == "speech_end":
                        pass

            if asr_commands.poll():
                command = asr_commands.recv()
                self.cfg['Logging']['system_logger'].info(command)

            if slu_commands.poll():
                command = slu_commands.recv()
                self.cfg['Logging']['system_logger'].info(command)

            if dm_commands.poll():
                command = dm_commands.recv()
                self.cfg['Logging']['system_logger'].info(command)

                if isinstance(command, Command):
                    if command.parsed['__name__'] == "hangup":
                        # prepare for ending the call
                        pass

                    if command.parsed['__name__'] == "dm_da_generated":
                        # record the time of the last system generated dialogue act
                        pass

            if nlg_commands.poll():
                command = nlg_commands.recv()
                # TODO HACK
                # self.cfg['Logging']['system_logger'].info(command)

            if tts_commands.poll():
                command = tts_commands.recv()
                # TODO HACK
                # self.cfg['Logging']['system_logger'].info(command)

            current_time = time.time()

        # stop processes
        aio_commands.send(Command('stop()', 'HUB', 'AIO'))
        vad_commands.send(Command('stop()', 'HUB', 'VAD'))
        asr_commands.send(Command('stop()', 'HUB', 'ASR'))
        slu_commands.send(Command('stop()', 'HUB', 'SLU'))
        dm_commands.send(Command('stop()', 'HUB', 'DM'))
        nlg_commands.send(Command('stop()', 'HUB', 'NLG'))
        tts_commands.send(Command('stop()', 'HUB', 'TTS'))

        # clean connections
        for c in command_connections:
            while c.poll():
                c.recv()

        for c in non_command_connections:
            while c.poll():
                c.recv()

        # wait for processes to stop
        aio.join()
        vad.join()
        tts.join()
Example #5
0
    tts_commands, tts_child_commands = multiprocessing.Pipe()  # used to send commands to TTS
    tts_text_in, tts_child_text_in = multiprocessing.Pipe()   # used to send TTS text

    command_connections = [aio_commands, vad_commands, asr_commands, tts_commands]

    non_command_connections = [aio_record, aio_child_record,
                               aio_play, aio_child_play,
                               vad_audio_out, vad_child_audio_out,
                               asr_hypotheses_out, asr_child_hypotheses,
                               tts_text_in, tts_child_text_in]

    close_event = multiprocessing.Event()

    aio = AudioIO(cfg, aio_child_commands, aio_child_record, aio_child_play, close_event)
    vad = VAD(cfg, vad_child_commands, aio_record, vad_child_audio_out, close_event)
    asr = ASR(cfg, asr_child_commands, vad_audio_out, asr_child_hypotheses, close_event)
    tts = TTS(cfg, tts_child_commands, tts_child_text_in, aio_play, close_event)

    aio.start()
    vad.start()
    asr.start()
    tts.start()

    tts_text_in.send(
        TTSText('Say something and the recognized text will be played back.'))

    count = 0
    max_count = 15000
    while count < max_count:
        time.sleep(cfg['Hub']['main_loop_sleep_time'])
        count += 1
Example #6
0
    def run(self):
        try:
            # AIO pipes
            # used to send commands to VoipIO
            aio_commands, aio_child_commands = multiprocessing.Pipe()
            # I read from this connection recorded audio
            aio_record, aio_child_record = multiprocessing.Pipe()
            # I write in audio to be played
            aio_play, aio_child_play = multiprocessing.Pipe()

            # VAD pipes
            # used to send commands to VAD
            vad_commands, vad_child_commands = multiprocessing.Pipe()
            # used to read output audio from VAD
            vad_audio_out, vad_child_audio_out = multiprocessing.Pipe()

            # ASR pipes
            # used to send commands to ASR
            asr_commands, asr_child_commands = multiprocessing.Pipe()
            # used to read ASR hypotheses
            asr_hypotheses_out, asr_child_hypotheses = multiprocessing.Pipe()

            # SLU pipes
            # used to send commands to SLU
            slu_commands, slu_child_commands = multiprocessing.Pipe()
            # used to read SLU hypotheses
            slu_hypotheses_out, slu_child_hypotheses = multiprocessing.Pipe()

            # DM pipes
            # used to send commands to DM
            dm_commands, dm_child_commands = multiprocessing.Pipe()
            # used to read DM actions
            dm_actions_out, dm_child_actions = multiprocessing.Pipe()

            # NLG pipes
            # used to send commands to NLG
            nlg_commands, nlg_child_commands = multiprocessing.Pipe()
            # used to read NLG output
            nlg_text_out, nlg_child_text = multiprocessing.Pipe()

            # TTS pipes
            # used to send commands to TTS
            tts_commands, tts_child_commands = multiprocessing.Pipe()


            command_connections = [aio_commands, vad_commands, asr_commands,
                                   slu_commands, dm_commands, nlg_commands,
                                   tts_commands]

            non_command_connections = [aio_record, aio_child_record,
                                       aio_play, aio_child_play,
                                       vad_audio_out, vad_child_audio_out,
                                       asr_hypotheses_out, asr_child_hypotheses,
                                       slu_hypotheses_out, slu_child_hypotheses,
                                       dm_actions_out, dm_child_actions,
                                       nlg_text_out, nlg_child_text]

            self.close_event = multiprocessing.Event()

            # create the hub components
            aio = AudioIO(self.cfg, aio_child_commands, aio_child_record, aio_child_play, self.close_event)
            vad = VAD(self.cfg, vad_child_commands, aio_record, vad_child_audio_out, self.close_event)
            asr = ASR(self.cfg, asr_child_commands, vad_audio_out, asr_child_hypotheses, self.close_event)
            slu = SLU(self.cfg, slu_child_commands, asr_hypotheses_out, slu_child_hypotheses, self.close_event)
            dm  =  DM(self.cfg,  dm_child_commands, slu_hypotheses_out, dm_child_actions, self.close_event)
            nlg = NLG(self.cfg, nlg_child_commands, dm_actions_out, nlg_child_text, self.close_event)
            tts = TTS(self.cfg, tts_child_commands, nlg_text_out, aio_play, self.close_event)

            # start the hub components
            aio.start()
            vad.start()
            asr.start()
            slu.start()
            dm.start()
            nlg.start()
            tts.start()

            self.cfg['Logging']['session_logger'].set_close_event(self.close_event)
            self.cfg['Logging']['session_logger'].set_cfg(self.cfg)
            self.cfg['Logging']['session_logger'].start()

            # init the system
            call_start = 0
            call_back_time = -1
            call_back_uri = None

            s_voice_activity = False
            s_last_voice_activity_time = 0
            u_voice_activity = False
            u_last_voice_activity_time = 0

            s_last_dm_activity_time = 0

            hangup = False

            call_start = time.time()

            self.cfg['Logging']['system_logger'].session_start("@LOCAL_CALL")
            self.cfg['Logging']['system_logger'].session_system_log('config = ' + str(self.cfg))

            self.cfg['Logging']['session_logger'].session_start(self.cfg['Logging']['system_logger'].get_session_dir_name())
            self.cfg['Logging']['session_logger'].config('config = ' + str(self.cfg))
            self.cfg['Logging']['session_logger'].header(self.cfg['Logging']["system_name"], self.cfg['Logging']["version"])
            self.cfg['Logging']['session_logger'].input_source("aio")


            while 1:
                # Check the close event.
                if self.close_event.is_set():
                    print 'Received close event in: %s' % multiprocessing.current_process().name
                    return

                time.sleep(self.cfg['Hub']['main_loop_sleep_time'])

                if call_back_time != -1 and call_back_time < time.time():
                    aio_commands.send(Command('make_call(destination="%s")' % \
                                              call_back_uri, 'HUB', 'AIO'))
                    call_back_time = -1
                    call_back_uri = None

                if vad_commands.poll():
                    command = vad_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "speech_start":
                            u_voice_activity = True
                        if command.parsed['__name__'] == "speech_end":
                            u_voice_activity = False
                            u_last_voice_activity_time = time.time()

                if asr_commands.poll():
                    command = asr_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                if slu_commands.poll():
                    command = slu_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                if dm_commands.poll():
                    command = dm_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "hangup":
                            # prepare for ending the call
                            hangup = True

                        if command.parsed['__name__'] == "dm_da_generated":
                            # record the time of the last system generated dialogue act
                            s_last_dm_activity_time = time.time()

                if nlg_commands.poll():
                    command = nlg_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                if tts_commands.poll():
                    command = tts_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                current_time = time.time()

            # stop processes
            aio_commands.send(Command('stop()', 'HUB', 'AIO'))
            vad_commands.send(Command('stop()', 'HUB', 'VAD'))
            asr_commands.send(Command('stop()', 'HUB', 'ASR'))
            slu_commands.send(Command('stop()', 'HUB', 'SLU'))
            dm_commands.send(Command('stop()', 'HUB', 'DM'))
            nlg_commands.send(Command('stop()', 'HUB', 'NLG'))
            tts_commands.send(Command('stop()', 'HUB', 'TTS'))

            # clean connections
            for c in command_connections:
                while c.poll():
                    c.recv()

            for c in non_command_connections:
                while c.poll():
                    c.recv()

            # wait for processes to stop
            # do not join, because in case of exception the join will not be successful
            # aio.join()
            # vad.join()
            # asr.join()
            # slu.join()
            # dm.join()
            # nlg.join()
            # tts.join()
            #cfg['Logging']['session_logger'].join()

        except KeyboardInterrupt:
            print 'KeyboardInterrupt exception in: %s' % multiprocessing.current_process().name
            self.close_event.set()
            return
        except:
            self.cfg['Logging']['system_logger'].exception('Uncaught exception in AHUB process.')
            self.close_event.set()
            raise

        print 'Exiting: %s. Setting close event' % multiprocessing.current_process().name
        self.close_event.set()
Example #7
0
File: vhub.py Project: choko/alex
    def run(self):
        try:
            vio_commands, vio_child_commands = multiprocessing.Pipe()  # used to send commands to VoipIO
            vio_record, vio_child_record = multiprocessing.Pipe()      # I read from this connection recorded audio
            vio_play, vio_child_play = multiprocessing.Pipe()          # I write in audio to be played

            vad_commands, vad_child_commands = multiprocessing.Pipe()   # used to send commands to VAD
            vad_audio_out, vad_child_audio_out = multiprocessing.Pipe() # used to read output audio from VAD

            asr_commands, asr_child_commands = multiprocessing.Pipe()          # used to send commands to ASR
            asr_hypotheses_out, asr_child_hypotheses = multiprocessing.Pipe()  # used to read ASR hypotheses

            slu_commands, slu_child_commands = multiprocessing.Pipe()          # used to send commands to SLU
            slu_hypotheses_out, slu_child_hypotheses = multiprocessing.Pipe()  # used to read SLU hypotheses

            dm_commands, dm_child_commands = multiprocessing.Pipe()            # used to send commands to DM
            dm_actions_out, dm_child_actions = multiprocessing.Pipe()          # used to read DM actions

            nlg_commands, nlg_child_commands = multiprocessing.Pipe()          # used to send commands to NLG
            nlg_text_out, nlg_child_text = multiprocessing.Pipe()              # used to read NLG output

            tts_commands, tts_child_commands = multiprocessing.Pipe()          # used to send commands to TTS

            command_connections = [vio_commands, vad_commands, asr_commands, slu_commands,
                                   dm_commands, nlg_commands, tts_commands]

            non_command_connections = [vio_record, vio_child_record,
                                       vio_play, vio_child_play,
                                       vad_audio_out, vad_child_audio_out,
                                       asr_hypotheses_out, asr_child_hypotheses,
                                       slu_hypotheses_out, slu_child_hypotheses,
                                       dm_actions_out, dm_child_actions,
                                       nlg_text_out, nlg_child_text]

            vio = VoipIO(self.cfg, vio_child_commands, vio_child_record, vio_child_play, self.close_event)
            vad = VAD(self.cfg, vad_child_commands, vio_record, vad_child_audio_out, self.close_event)
            asr = ASR(self.cfg, asr_child_commands, vad_audio_out, asr_child_hypotheses, self.close_event)
            slu = SLU(self.cfg, slu_child_commands, asr_hypotheses_out, slu_child_hypotheses, self.close_event)
            dm  =  DM(self.cfg,  dm_child_commands, slu_hypotheses_out, dm_child_actions, self.close_event)
            nlg = NLG(self.cfg, nlg_child_commands, dm_actions_out, nlg_child_text, self.close_event)
            tts = TTS(self.cfg, tts_child_commands, nlg_text_out, vio_play, self.close_event)

            vio.start()
            vad.start()
            asr.start()
            slu.start()
            dm.start()
            nlg.start()
            tts.start()

            self.write_pid_file([['vio', vio.pid], ['vad', vad.pid], ['asr', asr.pid],
                                 ['slu', slu.pid], ['dm', dm.pid], ['nlg', nlg.pid], ['tts', tts.pid]])

            cfg['Logging']['session_logger'].set_close_event(self.close_event)
            cfg['Logging']['session_logger'].set_cfg(cfg)
            cfg['Logging']['session_logger'].start()
            cfg['Logging']['session_logger'].cancel_join_thread()

            # init the system
            call_start = 0
            call_back_time = -1
            call_back_uri = None
            number_of_turns = -1

            s_voice_activity = False
            s_last_voice_activity_time = 0
            u_voice_activity = False
            u_last_voice_activity_time = 0

            s_last_dm_activity_time = 0

            u_last_input_timeout = 0

            call_connected = False
            hangup = False
            ncalls = 0

            outstanding_nlg_da = None

            call_db = CallDB(self.cfg, self.cfg['VoipHub']['call_db'], self.cfg['VoipHub']['period'])
            #call_db.log()

            while 1:
                # Check the close event.
                if self.close_event.is_set():
                    print 'Received close event in: %s' % multiprocessing.current_process().name
                    return

                time.sleep(self.cfg['Hub']['main_loop_sleep_time'])

                if call_back_time != -1 and call_back_time < time.time():
                    vio_commands.send(Command('make_call(destination="%s")' % call_back_uri, 'HUB', 'VoipIO'))
                    call_back_time = -1
                    call_back_uri = None

                # read all messages
                if vio_commands.poll():
                    command = vio_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):

                        if command.parsed['__name__'] == "incoming_call":
                            self.cfg['Logging']['system_logger'].session_start(command.parsed['remote_uri'])
                            self.cfg['Logging']['session_logger'].session_start(self.cfg['Logging']['system_logger'].get_session_dir_name())

                            self.cfg['Logging']['system_logger'].session_system_log('config = ' + unicode(self.cfg))
                            self.cfg['Logging']['session_logger'].config('config = ' + unicode(self.cfg))
                            self.cfg['Logging']['session_logger'].header(self.cfg['Logging']["system_name"], self.cfg['Logging']["version"])
                            self.cfg['Logging']['session_logger'].input_source("voip")

                            self.cfg['Analytics'].start_session(command.parsed['remote_uri'])
                            self.cfg['Analytics'].track_event('vhub', 'incoming_call', command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "rejected_call":
                            call_back_time = time.time() + self.cfg['VoipHub']['wait_time_before_calling_back']
                            call_back_uri = command.parsed['remote_uri']

                            self.cfg['Analytics'].track_event('vhub', 'rejected_call', command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "rejected_call_from_blacklisted_uri":
                            remote_uri = command.parsed['remote_uri']

                            num_all_calls, total_time, last_period_num_calls, last_period_total_time, last_period_num_short_calls = call_db.get_uri_stats(remote_uri)

                            m = []
                            m.append('')
                            m.append('=' * 120)
                            m.append('Rejected incoming call from blacklisted URI: %s' % remote_uri)
                            m.append('-' * 120)
                            m.append('Total calls:                  %d' % num_all_calls)
                            m.append('Total time (min):             %0.1f' % (total_time/60.0, ))
                            m.append('Last period short calls:      %d' % last_period_num_short_calls)
                            m.append('Last period total calls:      %d' % last_period_num_calls)
                            m.append('Last period total time (min): %0.1f' % (last_period_total_time/60.0, ))
                            m.append('=' * 120)
                            m.append('')
                            self.cfg['Logging']['system_logger'].info('\n'.join(m))

                            self.cfg['Analytics'].track_event('vhub', 'rejected_call_from_blacklisted_uri', command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "call_connecting":
                            self.cfg['Analytics'].track_event('vhub', 'call_connecting', command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "call_confirmed":
                            remote_uri = command.parsed['remote_uri']
                            num_all_calls, total_time, last_period_num_calls, last_period_total_time, last_period_num_short_calls  = call_db.get_uri_stats(remote_uri)

                            m = []
                            m.append('')
                            m.append('=' * 120)
                            m.append('Incoming call from :          %s' % remote_uri)
                            m.append('-' * 120)
                            m.append('Total calls:                  %d' % num_all_calls)
                            m.append('Total time (min):             %0.1f' % (total_time/60.0, ))
                            m.append('Last period short calls:      %d' % last_period_num_short_calls)
                            m.append('Last period total calls:      %d' % last_period_num_calls)
                            m.append('Last period total time (min): %0.1f' % (last_period_total_time/60.0, ))
                            m.append('-' * 120)

                            if last_period_num_calls > self.cfg['VoipHub']['last_period_max_num_calls'] or \
                                    last_period_total_time > self.cfg['VoipHub']['last_period_max_total_time'] or \
                                    last_period_num_short_calls > self.cfg['VoipHub']['last_period_max_num_short_calls'] :
                                # prepare for ending the call
                                call_connected = True

                                call_start = time.time()
                                number_of_turns = -1
                                s_voice_activity = True
                                s_last_voice_activity_time = time.time()
                                u_voice_activity = False
                                u_last_voice_activity_time = time.time()
                                u_last_input_timeout = time.time()
                                hangup = True

                                self.cfg['Logging']['session_logger'].turn("system")
                                tts_commands.send(Command('synthesize(text="%s",log="true")' % self.cfg['VoipHub']['limit_reached_message'], 'HUB', 'TTS'))
                                vio_commands.send(Command('black_list(remote_uri="%s",expire="%d")' % (remote_uri,
                                  time.time() + self.cfg['VoipHub']['blacklist_for']), 'HUB', 'VoipIO'))
                                m.append('CALL REJECTED')
                            else:
                                # init the system
                                call_connected = True

                                call_start = time.time()
                                number_of_turns = 0

                                s_voice_activity = False
                                s_last_voice_activity_time = 0
                                u_voice_activity = False
                                u_last_voice_activity_time = time.time()
                                u_last_input_timeout = time.time()
                                hangup = False

                                dm_commands.send(Command('new_dialogue()', 'HUB', 'DM'))
                                m.append('CALL ACCEPTED')

                            m.append('=' * 120)
                            m.append('')
                            self.cfg['Logging']['system_logger'].info('\n'.join(m))

                            call_db.track_confirmed_call(remote_uri)
                            self.cfg['Analytics'].track_event('vhub', 'call_confirmed', command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "call_disconnected":
                            # flush vio, when flushed, vad will be flushed
                            vio_commands.send(Command('flush()', 'HUB', 'VoipIO'))

                            self.cfg['Logging']['system_logger'].session_end()
                            self.cfg['Logging']['session_logger'].session_end()

                            remote_uri = command.parsed['remote_uri']
                            call_db.track_disconnected_call(remote_uri)

                            call_connected = False
                            number_of_turns = -1
                            ncalls += 1
                            
                            self.cfg['Analytics'].track_event('vhub', 'call_disconnected', command.parsed['remote_uri'])

                        if command.parsed['__name__'] == "play_utterance_start":
                            s_voice_activity = True
                            s_last_voice_activity_time = time.time()

                        if command.parsed['__name__'] == "play_utterance_end":
                            s_voice_activity = False
                            s_last_voice_activity_time = time.time()

                        if command.parsed['__name__'] == "flushed":
                            # flush vad, when flushed, asr will be flushed
                            vad_commands.send(Command('flush()', 'HUB', 'VAD'))

                        if command.parsed['__name__'] == "flushed_out":
                            # process the outstanding DA if necessary
                            if outstanding_nlg_da:
                                nlg_commands.send(DMDA(outstanding_nlg_da, 'HUB', 'NLG'))
                                outstanding_nlg_da = None


                if vad_commands.poll():
                    command = vad_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "speech_start":
                            u_voice_activity = True

                            # interrupt the talking system
                            # this will be replaced with pausing the system when the necessary extension of pjsip
                            # is implemented
                            if s_voice_activity and s_last_voice_activity_time + 0.02 < current_time:
                                # if the system is still talking then flush the output
                                self.cfg['Logging']['session_logger'].barge_in("system")

                                # when a user barge in into the output, all the output pipe line
                                # must be flushed
                                nlg_commands.send(Command('flush()', 'HUB', 'NLG'))
                                s_voice_activity = False
                                s_last_voice_activity_time = time.time()

                        if command.parsed['__name__'] == "speech_end":
                            u_voice_activity = False
                            u_last_voice_activity_time = time.time()

                        if command.parsed['__name__'] == "flushed":
                            # flush asr, when flushed, slu will be flushed
                            asr_commands.send(Command('flush()', 'HUB', 'ASR'))

                if asr_commands.poll():
                    command = asr_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "flushed":
                            # flush slu, when flushed, dm will be flushed
                            slu_commands.send(Command('flush()', 'HUB', 'SLU'))

                if slu_commands.poll():
                    command = slu_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "flushed":
                            # flush dm, when flushed, nlg will be flushed
                            dm_commands.send(Command('flush()', 'HUB', 'DM'))
                            dm_commands.send(Command('end_dialogue()', 'HUB', 'DM'))

                if dm_commands.poll():
                    command = dm_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "hangup":
                            # prepare for ending the call
                            hangup = True
                            self.cfg['Analytics'].track_event('vhub', 'system_hangup')

                        if command.parsed['__name__'] == "flushed":
                            # flush nlg, when flushed, tts will be flushed
                            nlg_commands.send(Command('flush()', 'HUB', 'NLG'))

                    elif isinstance(command, DMDA):
                        # record the time of the last system generated dialogue act
                        s_last_dm_activity_time = time.time()
                        number_of_turns += 1

                        if command.da != "silence()":
                            # if the DM generated non-silence dialogue act, then continue in processing it

                            if s_voice_activity and s_last_voice_activity_time + 0.02 < current_time:
                                # if the system is still talking then flush the output
                                self.cfg['Logging']['session_logger'].barge_in("system")

                                # when a user barge in into the output, all the output pipe line
                                # must be flushed
                                nlg_commands.send(Command('flush()', 'HUB', 'NLG'))
                                s_voice_activity = False
                                s_last_voice_activity_time = time.time()

                                # the DA will be send when all the following components are flushed
                                outstanding_nlg_da = command.da

                            else:
                                nlg_commands.send(DMDA(command.da, "HUB", "NLG"))

                if nlg_commands.poll():
                    command = nlg_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "flushed":
                            # flush tts, when flushed, vio will be flushed
                            tts_commands.send(Command('flush()', 'HUB', 'TTS'))

                if tts_commands.poll():
                    command = tts_commands.recv()
                    self.cfg['Logging']['system_logger'].info(command)

                    if isinstance(command, Command):
                        if command.parsed['__name__'] == "flushed":
                            # flush vio_out
                            vio_commands.send(Command('flush_out()', 'HUB', 'VIO'))

                current_time = time.time()

                s_diff = current_time - s_last_voice_activity_time
                u_diff = current_time - u_last_voice_activity_time

                if call_connected and \
                    not s_voice_activity and not u_voice_activity and \
                    s_diff > self.cfg['DM']['input_timeout'] and \
                    u_diff > self.cfg['DM']['input_timeout'] and \
                    current_time - u_last_input_timeout > self.cfg['DM']['input_timeout']:

                    u_last_input_timeout = time.time()
                    dm_commands.send(Command('timeout(silence_time="%0.3f")' % min(s_diff, u_diff), 'HUB', 'DM'))

                if hangup and s_last_dm_activity_time + 2.0 < current_time and \
                    s_voice_activity == False and s_last_voice_activity_time + 2.0 < current_time:
                    # we are ready to hangup only when all voice activity is finished
                    hangup = False
                    vio_commands.send(Command('hangup()', 'HUB', 'VoipIO'))

                if number_of_turns != -1 and current_time - call_start > self.cfg['VoipHub']['hard_time_limit'] or \
                    number_of_turns > self.cfg['VoipHub']['hard_turn_limit']:
                    # hard hangup due to the hard limits
                    call_start = 0
                    number_of_turns = -1
                    vio_commands.send(Command('hangup()', 'HUB', 'VoipIO'))

                if self.ncalls != 0 and not call_connected and s_last_dm_activity_time + 5.0 < current_time and ncalls >= self.ncalls:
                    break
                    
            # stop processes
            vio_commands.send(Command('stop()', 'HUB', 'VoipIO'))
            vad_commands.send(Command('stop()', 'HUB', 'VAD'))
            asr_commands.send(Command('stop()', 'HUB', 'ASR'))
            slu_commands.send(Command('stop()', 'HUB', 'SLU'))
            dm_commands.send(Command('stop()', 'HUB', 'DM'))
            nlg_commands.send(Command('stop()', 'HUB', 'NLG'))
            tts_commands.send(Command('stop()', 'HUB', 'TTS'))

            # clean connections
            for c in command_connections:
                while c.poll():
                    c.recv()

            for c in non_command_connections:
                while c.poll():
                    c.recv()

            # wait for processes to stop
            # do not join, because in case of exception the join will not be successful
            # vio.join()
            # vad.join()
            # asr.join()
            # slu.join()
            # dm.join()
            # nlg.join()
            # tts.join()
            #cfg['Logging']['session_logger'].join()

        except KeyboardInterrupt:
            print 'KeyboardInterrupt exception in: %s' % multiprocessing.current_process().name
            self.close_event.set()
            return
        except:
            self.cfg['Logging']['system_logger'].exception('Uncaught exception in VHUB process.')
            self.close_event.set()
            raise

        print 'Exiting: %s. Setting close event' % multiprocessing.current_process().name
        self.close_event.set()
Example #8
0
File: webhub.py Project: AoJ/alex
    def run(self):
        # AIO pipes
        # used to send commands to VoipIO
        aio_commands, aio_child_commands = multiprocessing.Pipe()
        # I read from this connection recorded audio
        aio_record, aio_child_record = multiprocessing.Pipe()
        # I write in audio to be played
        aio_play, aio_child_play = multiprocessing.Pipe()

        # VAD pipes
        # used to send commands to VAD
        vad_commands, vad_child_commands = multiprocessing.Pipe()
        # used to read output audio from VAD
        vad_audio_out, vad_child_audio_out = multiprocessing.Pipe()

        # ASR pipes
        # used to send commands to ASR
        asr_commands, asr_child_commands = multiprocessing.Pipe()
        # used to read ASR hypotheses
        asr_hypotheses_out, asr_child_hypotheses = multiprocessing.Pipe()

        # SLU pipes
        # used to send commands to SLU
        slu_commands, slu_child_commands = multiprocessing.Pipe()
        # used to read SLU hypotheses
        slu_hypotheses_out, slu_child_hypotheses = multiprocessing.Pipe()

        # DM pipes
        # used to send commands to DM
        dm_commands, dm_child_commands = multiprocessing.Pipe()
        # used to read DM actions
        dm_actions_out, dm_child_actions = multiprocessing.Pipe()

        # NLG pipes
        # used to send commands to NLG
        nlg_commands, nlg_child_commands = multiprocessing.Pipe()
        # used to read NLG output
        nlg_text_out, nlg_child_text = multiprocessing.Pipe()

        # TTS pipes
        # used to send commands to TTS
        tts_commands, tts_child_commands = multiprocessing.Pipe()

        command_connections = [aio_commands, vad_commands, asr_commands,
                               slu_commands, dm_commands, nlg_commands,
                               tts_commands]

        non_command_connections = [aio_record, aio_child_record,
                                   aio_play, aio_child_play,
                                   vad_audio_out, vad_child_audio_out,
                                   asr_hypotheses_out, asr_child_hypotheses,
                                   slu_hypotheses_out, slu_child_hypotheses,
                                   dm_actions_out, dm_child_actions,
                                   nlg_text_out, nlg_child_text]

        # create the hub components
        close_event = multiprocessing.Event()
        aio = WebIO(self.cfg, aio_child_commands, aio_child_record, aio_child_play, close_event)
        vad = VAD(self.cfg, vad_child_commands, aio_record, vad_child_audio_out, close_event)
        asr = ASR(self.cfg, asr_child_commands, vad_audio_out, asr_child_hypotheses, close_event)
        slu = SLU(
            self.cfg, slu_child_commands, asr_hypotheses_out, slu_child_hypotheses, close_event)
        dm = DM(self.cfg, dm_child_commands, slu_hypotheses_out, dm_child_actions, close_event)
        nlg = NLG(self.cfg, nlg_child_commands, dm_actions_out, nlg_child_text, close_event)
        tts = TTS(self.cfg, tts_child_commands, nlg_text_out, aio_play, close_event)

        # start the hub components
        aio.start()
        vad.start()
        asr.start()
        slu.start()
        dm.start()
        nlg.start()
        tts.start()

        # init the system
        call_back_time = -1
        call_back_uri = None
        call_start = time.time()

        self.cfg['Logging']['system_logger'].session_start("@LOCAL_CALL")
        self.cfg['Logging']['system_logger'].session_system_log('config = ' + str(self.cfg))

        self.cfg['Logging']['session_logger'].session_start(
            self.cfg['Logging']['system_logger'].get_session_dir_name())
        self.cfg['Logging']['session_logger'].config('config = ' + str(self.cfg))
        self.cfg['Logging']['session_logger'].header(
            self.cfg['Logging']["system_name"], self.cfg['Logging']["version"])
        self.cfg['Logging']['session_logger'].input_source("aio")

        while 1:
            time.sleep(self.cfg['Hub']['main_loop_sleep_time'])

            if call_back_time != -1 and call_back_time < time.time():
                aio_commands.send(Command('make_call(destination="%s")' %
                                          call_back_uri, 'HUB', 'AIO'))
                call_back_time = -1
                call_back_uri = None

            if vad_commands.poll():
                command = vad_commands.recv()
                self.cfg['Logging']['system_logger'].info(command)

                if isinstance(command, Command):
                    if command.parsed['__name__'] == "speech_start":
                        pass
                    if command.parsed['__name__'] == "speech_end":
                        pass

            if asr_commands.poll():
                command = asr_commands.recv()
                self.cfg['Logging']['system_logger'].info(command)

            if slu_commands.poll():
                command = slu_commands.recv()
                self.cfg['Logging']['system_logger'].info(command)

            if dm_commands.poll():
                command = dm_commands.recv()
                self.cfg['Logging']['system_logger'].info(command)

                if isinstance(command, Command):
                    if command.parsed['__name__'] == "hangup":
                        # prepare for ending the call
                        pass

                    if command.parsed['__name__'] == "dm_da_generated":
                        # record the time of the last system generated dialogue act
                        pass

            if nlg_commands.poll():
                command = nlg_commands.recv()
                # TODO HACK
                # self.cfg['Logging']['system_logger'].info(command)

            if tts_commands.poll():
                command = tts_commands.recv()
                # TODO HACK
                # self.cfg['Logging']['system_logger'].info(command)

            current_time = time.time()

        # stop processes
        aio_commands.send(Command('stop()', 'HUB', 'AIO'))
        vad_commands.send(Command('stop()', 'HUB', 'VAD'))
        asr_commands.send(Command('stop()', 'HUB', 'ASR'))
        slu_commands.send(Command('stop()', 'HUB', 'SLU'))
        dm_commands.send(Command('stop()', 'HUB', 'DM'))
        nlg_commands.send(Command('stop()', 'HUB', 'NLG'))
        tts_commands.send(Command('stop()', 'HUB', 'TTS'))

        # clean connections
        for c in command_connections:
            while c.poll():
                c.recv()

        for c in non_command_connections:
            while c.poll():
                c.recv()

        # wait for processes to stop
        aio.join()
        vad.join()
        tts.join()