Example #1
0
 def get_current_cmdproc(self):
     current_cmdproc = None
     if self._is_sending or self._is_talking:
         current_cmdproc = self._receiving_cmdproc
     else:
         current_program = window.get_current_program()
         if current_program in self._cmdproc_config:
             # current window takes priority.
             current_cmdproc = current_program
             # the user is switched to the program and commanding it directly (when they lose focus,
             # they probably expect to continue speaking to that application).
             # self._last_focussed = current_program
         elif self._last_focussed is not None:
             # otherwise use the program that last had activity
             current_cmdproc = self._last_focussed
     return current_cmdproc
Example #2
0
 def get_current_cmdproc(self):
     current_cmdproc = None
     if self._is_sending or self._is_talking:
         current_cmdproc = self._receiving_cmdproc
     else:
         current_program = window.get_current_program()
         if current_program in self._cmdproc_config:
             # current window takes priority.
             current_cmdproc = current_program
             # the user is switched to the program and commanding it directly (when they lose focus, 
             # they probably expect to continue speaking to that application).
             # self._last_focussed = current_program
         elif self._last_focussed is not None:
             # otherwise use the program that last had activity
             current_cmdproc = self._last_focussed
     return current_cmdproc
Example #3
0
    def cmd(self, words, callback, err):
        """
        Interpret a command for the server or the current in focus application.

        Call callback when we're ready to handle the next command.

        When receiving a bad command, an exception will be called as an argument to err.
        """

        last_focussed = self._cmdserver.get_last_focussed_cmdproc()
        logger.info("LAST FOCUSSED: %s", last_focussed)

        if self._asking_for_input:
            logger.info(
                "We're asking the user for input, hold off on commands for now..."
            )
            return

        cmd = []

        def consume(i, cmd_str):
            if i >= len(words):
                err(IncompleteCmdServerCommand(cmd))
                return
            elif words[i] == cmd_str:
                cmd.append(['cmd', cmd_str])
            else:
                # TODO: wrong, shouldn't call err here (unless last command tried)
                err(BadCmdServerCommand(cmd, words[i]))
                return

        def is_cmd(*cmd_strs):
            if len(words) < len(cmd_strs):
                return False
            new_cmd = []
            for i in range(len(cmd_strs)):
                if type(cmd_strs[i]) == str:
                    if words[i] != cmd_strs[i]:
                        return False
                    new_cmd.append(['cmd', words[i]])
                elif cmd_strs[i] == ['cmdproc']:
                    if words[i] not in self._cmdproc_delims:
                        return False
                    new_cmd.append(['cmdproc', words[i]])
            cmd.extend(new_cmd)
            return True

        if not self._cmdserver.listening:
            if is_cmd('WAKEUP', 'CALM'):
                self._cmdserver.wakeup()
                callback()
                return
            elif is_cmd('HELP'):
                self._cmdserver.notify_server(
                    'Calm is sleeping', 'Say WAKEUP CALM to get started')
                callback()
                return
            else:
                # We're ignoring input since we're sleeping
                callback()
                return
        elif is_cmd('SLEEP'):
            self._cmdserver.sleep()
            callback()
            return
        elif is_cmd('HELP'):
            self._cmdserver.cmd_help()
            callback()
            return

        # TODO: add try / except and then handle current application in focus
        # logger.info("is sending?? %s", self._is_sending)
        if self._is_sending:
            cmdproc_cmd = None
            if is_cmd('FINISH', 'SENDING'):
                self.done_sending()
                callback()
                return
            elif is_cmd('SEND', ['cmdproc']) or is_cmd('SEND', 'TO',
                                                       ['cmdproc']):
                # index of cmdproc
                i = len(cmd) - 1
                cmdproc = cmd[i][1].lower()

                if cmdproc != self._cmdserver._receiving_cmdproc:
                    # Sometimes the user will not notice they've switched to sending to a
                    # cmdproc, so let them switch.
                    #
                    # Otherwise, the user might not have not have noticed their switch to
                    # sending to the application, so they're trying the whole "SEND
                    # <PROGRAM> cmd" phrase. Extract it and send it off.
                    self.switch_to_sending(cmdproc)
                cmdproc_cmd = words[i + 1:]
            else:
                cmdproc_cmd = words

            def send_cmd_cb(cmd):
                self._cmdserver.send_cmd(self._cmdserver._receiving_cmdproc,
                                         cmd)
                self.done_sending()
                callback()

            self.cmdproc_cmd(self._cmdserver._receiving_cmdproc, cmdproc_cmd,
                             send_cmd_cb, err)
            return

        if len(words) < 1:
            err(IncompleteCmdServerCommand(cmd))
            return

        def ask_for_program(cb, description):
            # TODO: use voice for this
            def get_ready_to_send_cb(cmdproc):
                # logger.info("send to... %s", cmdproc)
                if cmdproc not in self._cmdserver._cmdproc_config:
                    # self.error("No such program named {cmdproc}".format(**locals()))
                    # raise BadCmdServerCommand(cmd, cmdproc)
                    err(BadCmdServerCommand(cmd, cmdproc))
                    return
                cb(cmdproc)

            self.ask_for_string(
                'program to {description} to'.format(**locals()),
                get_ready_to_send_cb, self._cmdserver._cmdproc_config.keys())

        def talk_to_cb(cmdproc):
            if self._talking_to_cmdproc:
                # We're already talking to a cmdproc; switch to talking to this cmdproc
                self.done_talking(self._cmdserver._receiving_cmdproc)
            self.get_ready_to_talk(cmdproc)
            callback()

        def send_cb(cmdproc):
            self.get_ready_to_send(cmdproc)
            callback()

        if is_cmd('TALK', 'TO', ['cmdproc']):
            talk_to_cb(cmd[2][1].lower())
            return
        elif is_cmd('TALK'):
            ask_for_program(talk_to_cb, description='talk')
            return
        elif is_cmd('FINISH', 'TALKING'):
            if self._talking_to_cmdproc:
                self.done_talking(self._cmdserver._receiving_cmdproc)
            callback()
            return
        elif is_cmd('SEND', ['cmdproc']) or is_cmd('SEND', 'TO', ['cmdproc']):
            # index of cmdproc
            i = len(cmd) - 1
            cmdproc = cmd[i][1].lower()
            if len(words) == i + 1:
                # the user only specified the command
                send_cb(cmdproc)
            else:
                # the user may be trying to send a command all in one sentence; try to send everything
                # after SEND TO <cmdproc> to the cmdproc, but if it rejects, fall back to the SEND TO
                # <cmdproc>
                def fallback(cmdproc_error):
                    send_cb(cmdproc)

                def send_cmd_cb(cmdproc_cmd):
                    # no need to notify of the receiving process, or use done_sending
                    self._cmdserver.send_cmd(cmdproc, cmdproc_cmd)
                    callback()

                self.cmdproc_cmd(cmdproc,
                                 words[i + 1:],
                                 send_cmd_cb,
                                 err=fallback)
            return
        elif is_cmd('SEND'):
            ask_for_program(send_cb, description='send')
            return
        elif is_cmd('RECORD'):

            def start_recording_cb(macroname):
                if macroname is not None:
                    self._cmdserver.record_macro(macroname)
                callback()

            self.ask_for_string('the name of your recording',
                                start_recording_cb, self._cmdserver.macros)
            return
        elif is_cmd('FINISH', 'MACRO'):
            self._cmdserver.end_macro()
            callback()
            return
        elif is_cmd('REPLAY'):

            def replay_macro_cb(macroname):
                self._cmdserver.replay_macro(macroname)
                callback()

            self.ask_for_string('the recording to replay', replay_macro_cb,
                                self._cmdserver.macros)
            return
        elif is_cmd('UNDO'):
            if self._cmdserver.is_recording:
                self._cmdserver.undo_last_cmd()
            callback()
            return

        def cmdproc_and_cmdserver_err(e):
            if type(e) == BadCmdProcCommandInput:
                err(e)
            else:
                err(
                    NeitherCmdProcOrServerCommand(
                        e, BadCmdServerCommand(cmd, words[0])))

        def send_cmd_to_cmdproc(cmdproc, err):
            """
            Sending a command to a command processor:
            - try the current application with priority if it is a command processor
            - otherwise, send to the last focussed application
            (either the current application, or an application 
            we're talking to).
            """
            def send_cmd_cb(cmd):
                self._cmdserver.send_cmd(cmdproc, cmd)
                callback()

            self.cmdproc_cmd(cmdproc, words, send_cmd_cb, err)

        # See if we're talking to a specific command processor
        if self._talking_to_cmdproc:
            send_cmd_to_cmdproc(self._cmdserver._receiving_cmdproc,
                                cmdproc_and_cmdserver_err)
            return

        # Sending a command to a command processor:
        # - try the current application with priority if it is a command processor
        # - otherwise, send to the last focussed application

        def send_to_last_focussed(*args):
            if self._cmdserver._last_focussed is not None:
                send_cmd_to_cmdproc(self._cmdserver._last_focussed,
                                    cmdproc_and_cmdserver_err)
            else:
                # No command processor available; interpret as a bad server command.
                err(BadCmdServerCommand(cmd, words[0]))

        current_window = window.get_current_program()
        if current_window in self._cmdserver._cmdproc_config:
            send_cmd_to_cmdproc(current_window, send_to_last_focussed)
            return
        else:
            send_to_last_focussed()
            return
Example #4
0
    def cmd(self, words, callback, err):
        """
        Interpret a command for the server or the current in focus application.

        Call callback when we're ready to handle the next command.

        When receiving a bad command, an exception will be called as an argument to err.
        """

        last_focussed = self._cmdserver.get_last_focussed_cmdproc()
        logger.info("LAST FOCUSSED: %s", last_focussed)

        if self._asking_for_input:
            logger.info("We're asking the user for input, hold off on commands for now...")
            return

        cmd = []
        def consume(i, cmd_str):
            if i >= len(words):
                err(IncompleteCmdServerCommand(cmd))
                return
            elif words[i] == cmd_str:
                cmd.append(['cmd', cmd_str])
            else:
                # TODO: wrong, shouldn't call err here (unless last command tried)
                err(BadCmdServerCommand(cmd, words[i]))
                return

        def is_cmd(*cmd_strs):
            if len(words) < len(cmd_strs):
                return False
            new_cmd = []
            for i in range(len(cmd_strs)):
                if type(cmd_strs[i]) == str:
                    if words[i] != cmd_strs[i]:
                        return False
                    new_cmd.append(['cmd', words[i]])
                elif cmd_strs[i] == ['cmdproc']:
                    if words[i] not in self._cmdproc_delims:
                        return False
                    new_cmd.append(['cmdproc', words[i]])
            cmd.extend(new_cmd)
            return True

        if not self._cmdserver.listening:
            if is_cmd('WAKEUP', 'CALM'):
                self._cmdserver.wakeup()
                callback()
                return
            elif is_cmd('HELP'):
                self._cmdserver.notify_server('Calm is sleeping', 'Say WAKEUP CALM to get started')
                callback()
                return
            else:
                # We're ignoring input since we're sleeping
                callback()
                return
        elif is_cmd('SLEEP'):
            self._cmdserver.sleep()
            callback()
            return
        elif is_cmd('HELP'):
            self._cmdserver.cmd_help()
            callback()
            return

        # TODO: add try / except and then handle current application in focus
        # logger.info("is sending?? %s", self._is_sending)
        if self._is_sending:
            cmdproc_cmd = None
            if is_cmd('FINISH', 'SENDING'):
                self.done_sending()
                callback()
                return
            elif is_cmd('SEND', ['cmdproc']) or is_cmd('SEND', 'TO', ['cmdproc']):
                # index of cmdproc
                i = len(cmd) - 1
                cmdproc = cmd[i][1].lower()

                if cmdproc != self._cmdserver._receiving_cmdproc:
                    # Sometimes the user will not notice they've switched to sending to a 
                    # cmdproc, so let them switch.
                    #
                    # Otherwise, the user might not have not have noticed their switch to 
                    # sending to the application, so they're trying the whole "SEND 
                    # <PROGRAM> cmd" phrase. Extract it and send it off.
                    self.switch_to_sending(cmdproc)
                cmdproc_cmd = words[i + 1:]
            else:
                cmdproc_cmd = words
            def send_cmd_cb(cmd):
                self._cmdserver.send_cmd(self._cmdserver._receiving_cmdproc, cmd)
                self.done_sending()
                callback()
            self.cmdproc_cmd(self._cmdserver._receiving_cmdproc, cmdproc_cmd, send_cmd_cb, err)
            return

        if len(words) < 1:
            err(IncompleteCmdServerCommand(cmd))
            return

        def ask_for_program(cb, description):
            # TODO: use voice for this
            def get_ready_to_send_cb(cmdproc):
                # logger.info("send to... %s", cmdproc)
                if cmdproc not in self._cmdserver._cmdproc_config:
                    # self.error("No such program named {cmdproc}".format(**locals()))
                    # raise BadCmdServerCommand(cmd, cmdproc)
                    err(BadCmdServerCommand(cmd, cmdproc))
                    return
                cb(cmdproc)
            self.ask_for_string('program to {description} to'.format(**locals()), get_ready_to_send_cb, self._cmdserver._cmdproc_config.keys())

        def talk_to_cb(cmdproc):
            if self._talking_to_cmdproc:
                # We're already talking to a cmdproc; switch to talking to this cmdproc
                self.done_talking(self._cmdserver._receiving_cmdproc)
            self.get_ready_to_talk(cmdproc)
            callback()
        def send_cb(cmdproc):
            self.get_ready_to_send(cmdproc)
            callback()
        if is_cmd('TALK', 'TO', ['cmdproc']):
            talk_to_cb(cmd[2][1].lower())
            return
        elif is_cmd('TALK'):
            ask_for_program(talk_to_cb, description='talk')
            return
        elif is_cmd('FINISH', 'TALKING'):
            if self._talking_to_cmdproc:
                self.done_talking(self._cmdserver._receiving_cmdproc)
            callback()
            return
        elif is_cmd('SEND', ['cmdproc']) or is_cmd('SEND', 'TO', ['cmdproc']):
            # index of cmdproc
            i = len(cmd) - 1
            cmdproc = cmd[i][1].lower()
            if len(words) == i + 1:
                # the user only specified the command
                send_cb(cmdproc)
            else:
                # the user may be trying to send a command all in one sentence; try to send everything 
                # after SEND TO <cmdproc> to the cmdproc, but if it rejects, fall back to the SEND TO 
                # <cmdproc>
                def fallback(cmdproc_error):
                    send_cb(cmdproc)
                def send_cmd_cb(cmdproc_cmd):
                    # no need to notify of the receiving process, or use done_sending 
                    self._cmdserver.send_cmd(cmdproc, cmdproc_cmd)
                    callback()
                self.cmdproc_cmd(cmdproc, words[i + 1:], send_cmd_cb, err=fallback)
            return
        elif is_cmd('SEND'):
            ask_for_program(send_cb, description='send')
            return
        elif is_cmd('RECORD'):
            def start_recording_cb(macroname):
                if macroname is not None:
                    self._cmdserver.record_macro(macroname)
                callback()
            self.ask_for_string('the name of your recording', start_recording_cb, self._cmdserver.macros)
            return
        elif is_cmd('FINISH', 'MACRO'):
            self._cmdserver.end_macro()
            callback()
            return
        elif is_cmd('REPLAY'):
            def replay_macro_cb(macroname):
                self._cmdserver.replay_macro(macroname)
                callback()
            self.ask_for_string('the recording to replay', replay_macro_cb, self._cmdserver.macros)
            return
        elif is_cmd('UNDO'):
            if self._cmdserver.is_recording:
                self._cmdserver.undo_last_cmd()
            callback()
            return

        def cmdproc_and_cmdserver_err(e):
            if type(e) == BadCmdProcCommandInput:
                err(e)
            else:
                err(NeitherCmdProcOrServerCommand(e, BadCmdServerCommand(cmd, words[0])))
        def send_cmd_to_cmdproc(cmdproc, err):
            """
            Sending a command to a command processor:
            - try the current application with priority if it is a command processor
            - otherwise, send to the last focussed application
            (either the current application, or an application 
            we're talking to).
            """
            def send_cmd_cb(cmd):
                self._cmdserver.send_cmd(cmdproc, cmd)
                callback()
            self.cmdproc_cmd(cmdproc, words, send_cmd_cb, err)

        # See if we're talking to a specific command processor
        if self._talking_to_cmdproc:
            send_cmd_to_cmdproc(self._cmdserver._receiving_cmdproc, cmdproc_and_cmdserver_err)
            return

        # Sending a command to a command processor:
        # - try the current application with priority if it is a command processor
        # - otherwise, send to the last focussed application

        def send_to_last_focussed(*args):
            if self._cmdserver._last_focussed is not None:
                send_cmd_to_cmdproc(self._cmdserver._last_focussed, cmdproc_and_cmdserver_err)
            else:
                # No command processor available; interpret as a bad server command.
                err(BadCmdServerCommand(cmd, words[0]))
        current_window = window.get_current_program()
        if current_window in self._cmdserver._cmdproc_config:
            send_cmd_to_cmdproc(current_window, send_to_last_focussed)
            return
        else:
            send_to_last_focussed()
            return